Working roboport power connection.
This commit is contained in:
parent
a748708998
commit
068297e2c2
5 changed files with 258 additions and 15 deletions
|
|
@ -538,7 +538,10 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
|
||||||
b.add_blueprint(multistation_blueprint);
|
b.add_blueprint(multistation_blueprint);
|
||||||
|
|
||||||
b.add_roboport_network();
|
b.add_roboport_network();
|
||||||
|
b.print_visualization();
|
||||||
|
b.connect_roboport_power();
|
||||||
|
|
||||||
|
b.print_visualization();
|
||||||
b.connect_power_networks();
|
b.connect_power_networks();
|
||||||
|
|
||||||
b
|
b
|
||||||
|
|
|
||||||
|
|
@ -441,7 +441,7 @@ impl Entity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ElectricPoleType::Substation => {
|
ElectricPoleType::Substation => {
|
||||||
for (dx, dy) in [(-1, -1), (1, -1), (-1, 1), (1, 1)] {
|
for (dx, dy) in [(-2, -2), (0, -2), (-2, 0), (0, 0)] {
|
||||||
v.add_symbol(
|
v.add_symbol(
|
||||||
(self.position + Position::new(dx, dy)) / 2 + offset,
|
(self.position + Position::new(dx, dy)) / 2 + offset,
|
||||||
factorio_core::visualize::Symbol::Char('S'),
|
factorio_core::visualize::Symbol::Char('S'),
|
||||||
|
|
@ -451,6 +451,18 @@ impl Entity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
EntityType::Roboport => {
|
||||||
|
for dx in -2..2 {
|
||||||
|
for dy in -2..2 {
|
||||||
|
v.add_symbol(
|
||||||
|
(self.position) / 2 + Position::new(dx, dy) + offset,
|
||||||
|
factorio_core::visualize::Symbol::Char('R'),
|
||||||
|
Some(Color::yellow()),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
|
use std::ops::Index;
|
||||||
|
|
||||||
|
use factorio_core::visualize::Visualize;
|
||||||
use factorio_graph::{
|
use factorio_graph::{
|
||||||
|
graph::Graph,
|
||||||
priority_queue::binary_heap::FastBinaryHeap,
|
priority_queue::binary_heap::FastBinaryHeap,
|
||||||
wheighted_graph::{WheightedGraph, steiner_tree},
|
wheighted_graph::{WheightedGraph, shortest_path::dijkstra, steiner_tree},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -155,16 +159,6 @@ impl Blueprint {
|
||||||
|
|
||||||
if let Some(cost) = cost {
|
if let Some(cost) = cost {
|
||||||
let v = power_connections(Position::new(x, y), electric_pole_type)
|
let v = power_connections(Position::new(x, y), electric_pole_type)
|
||||||
// .filter(|&(pos, _)| aabb.contains_pos(pos))
|
|
||||||
// .inspect(|d| {
|
|
||||||
// if y == 261 {
|
|
||||||
// dbg!(d);
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// .filter(|&(pos, electric_pole_type)| {
|
|
||||||
// placibility.placeable(pos, electric_pole_type.size())
|
|
||||||
// || power_pole_map.contains_key(&(pos, electric_pole_type))
|
|
||||||
// })
|
|
||||||
.collect();
|
.collect();
|
||||||
nodes.insert((Position::new(x, y), electric_pole_type), (v, cost));
|
nodes.insert((Position::new(x, y), electric_pole_type), (v, cost));
|
||||||
}
|
}
|
||||||
|
|
@ -230,3 +224,228 @@ impl Blueprint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MultistartGraph<'a, G: WheightedGraph> {
|
||||||
|
graph: &'a G,
|
||||||
|
start_nodes: Vec<G::Node>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G: WheightedGraph> WheightedGraph for MultistartGraph<'_, G>
|
||||||
|
where
|
||||||
|
G::Node: Clone,
|
||||||
|
{
|
||||||
|
type Node = Option<G::Node>;
|
||||||
|
|
||||||
|
fn edge(&self, node: &Self::Node, num: usize) -> Option<(Self::Node, f64)> {
|
||||||
|
match node {
|
||||||
|
Some(n) => self.graph.edge(n, num).map(|(e, w)| (Some(e), w)),
|
||||||
|
None => self.start_nodes.get(num).map(|n| (Some(n.clone()), 0.0)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Blueprint {
|
||||||
|
pub fn connect_roboport_power(&mut self) {
|
||||||
|
let mut roboportmap = self
|
||||||
|
.entities
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(k, e)| match e.entity {
|
||||||
|
EntityType::Roboport => Some(e.position),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if roboportmap.len() == 0 {
|
||||||
|
return;
|
||||||
|
} else if roboportmap.len() == 1 {
|
||||||
|
let roboport = roboportmap.into_iter().next().unwrap();
|
||||||
|
for (x, y) in ((roboport.x - 8)..=(roboport.x + 8))
|
||||||
|
.filter(move |x| x.rem_euclid(2) == 1)
|
||||||
|
.flat_map(|x| {
|
||||||
|
((roboport.y - 8)..=(roboport.y + 8))
|
||||||
|
.filter(move |y| y.rem_euclid(2) == 1)
|
||||||
|
.map(move |y| (x, y))
|
||||||
|
})
|
||||||
|
{
|
||||||
|
if self.placeable(Position::new(x, y), Position::new(2, 2)) {
|
||||||
|
self.add_entity(Entity::new_electric_pole(
|
||||||
|
super::ElectricPoleType::Small,
|
||||||
|
Position::new(x, y),
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic!("unable to place power pole around roboport");
|
||||||
|
}
|
||||||
|
|
||||||
|
let aabb = self.get_aabb().unwrap();
|
||||||
|
|
||||||
|
let start_roboport = roboportmap.pop().unwrap();
|
||||||
|
|
||||||
|
let mut start_nodes = Vec::new();
|
||||||
|
|
||||||
|
{
|
||||||
|
let placibility = self.placibility_map();
|
||||||
|
for (electric_pole_type, dist) in [
|
||||||
|
(ElectricPoleType::Small, 9),
|
||||||
|
(ElectricPoleType::Medium, 11),
|
||||||
|
(ElectricPoleType::Big, 6),
|
||||||
|
] {
|
||||||
|
for (x, y) in
|
||||||
|
((start_roboport.x - dist)..=(start_roboport.x + dist)).flat_map(|x| {
|
||||||
|
((start_roboport.y - dist)..=(start_roboport.y + dist)).map(move |y| (x, y))
|
||||||
|
})
|
||||||
|
{
|
||||||
|
// dbg!(x, y, electric_pole_type);
|
||||||
|
let alignment = electric_pole_type.alignment();
|
||||||
|
if x.rem_euclid(2) == alignment && y.rem_euclid(2) == alignment {
|
||||||
|
if placibility.placeable(Position::new(x, y), electric_pole_type.size()) {
|
||||||
|
start_nodes.push(Node {
|
||||||
|
pos: Position::new(x, y),
|
||||||
|
electric_pole_type,
|
||||||
|
node_type: NodeType::In,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut visited_roboports = vec![start_roboport];
|
||||||
|
|
||||||
|
while !roboportmap.is_empty() {
|
||||||
|
let placibility = self.placibility_map();
|
||||||
|
let mut power_pole_map = self
|
||||||
|
.entities
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(k, e)| match e.entity {
|
||||||
|
EntityType::ElectricPole(electric_pole_type) => {
|
||||||
|
Some(((e.position, electric_pole_type), *k))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
let mut nodes = HashMap::new();
|
||||||
|
for y in aabb.min().y..=aabb.max().y {
|
||||||
|
for x in aabb.min().x..=aabb.max().x {
|
||||||
|
for electric_pole_type in [
|
||||||
|
ElectricPoleType::Small,
|
||||||
|
ElectricPoleType::Medium,
|
||||||
|
ElectricPoleType::Big,
|
||||||
|
] {
|
||||||
|
// dbg!(x, y, electric_pole_type);
|
||||||
|
let alignment = electric_pole_type.alignment();
|
||||||
|
if x.rem_euclid(2) == alignment
|
||||||
|
&& y.rem_euclid(2) == alignment
|
||||||
|
&& visited_roboports
|
||||||
|
.iter()
|
||||||
|
.any(|p| p.x.abs_diff(x) < 110 && p.y.abs_diff(y) < 110)
|
||||||
|
{
|
||||||
|
let cost = if placibility
|
||||||
|
.placeable(Position::new(x, y), electric_pole_type.size())
|
||||||
|
{
|
||||||
|
Some(match electric_pole_type {
|
||||||
|
ElectricPoleType::Small => 0.8,
|
||||||
|
ElectricPoleType::Medium => 1.0,
|
||||||
|
ElectricPoleType::Big => 1.5,
|
||||||
|
ElectricPoleType::Substation => todo!(),
|
||||||
|
})
|
||||||
|
} else if power_pole_map
|
||||||
|
.contains_key(&(Position::new(x, y), electric_pole_type))
|
||||||
|
{
|
||||||
|
Some(0.0)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(cost) = cost {
|
||||||
|
let v = power_connections(Position::new(x, y), electric_pole_type)
|
||||||
|
.collect();
|
||||||
|
nodes.insert((Position::new(x, y), electric_pole_type), (v, cost));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let power_graph = PowerGraph { nodes };
|
||||||
|
|
||||||
|
let multistart_graph = MultistartGraph {
|
||||||
|
graph: &power_graph,
|
||||||
|
start_nodes: start_nodes.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let p = dijkstra::<_, FastBinaryHeap<_>, _>(&multistart_graph, None, |p| {
|
||||||
|
if let Some(n) = p {
|
||||||
|
match n.node_type {
|
||||||
|
NodeType::In => false,
|
||||||
|
NodeType::Out => {
|
||||||
|
let dist = match n.electric_pole_type {
|
||||||
|
ElectricPoleType::Small => 7,
|
||||||
|
ElectricPoleType::Medium => 9,
|
||||||
|
ElectricPoleType::Big => 6,
|
||||||
|
ElectricPoleType::Substation => todo!(),
|
||||||
|
};
|
||||||
|
roboportmap.iter().any(|r| {
|
||||||
|
r.x.abs_diff(n.pos.x) <= dist && r.y.abs_diff(n.pos.y) <= dist
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(path) = p {
|
||||||
|
start_nodes = vec![path[1].unwrap()];
|
||||||
|
|
||||||
|
let path_iter = path.iter().filter_map(|n| n.as_ref()).filter_map(
|
||||||
|
|Node {
|
||||||
|
pos,
|
||||||
|
electric_pole_type,
|
||||||
|
node_type,
|
||||||
|
}| match node_type {
|
||||||
|
NodeType::In => None,
|
||||||
|
NodeType::Out => Some((*pos, *electric_pole_type)),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
for p in path_iter.clone() {
|
||||||
|
match power_pole_map.entry(p) {
|
||||||
|
std::collections::hash_map::Entry::Occupied(_occupied_entry) => (),
|
||||||
|
std::collections::hash_map::Entry::Vacant(vacant_entry) => {
|
||||||
|
let k = self.add_entity(Entity::new_electric_pole(p.1, p.0));
|
||||||
|
vacant_entry.insert(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (p, n) in path_iter.clone().zip(path_iter.skip(1)) {
|
||||||
|
self.add_wire(power_pole_map[&n], 5, power_pole_map[&p], 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
let last_node = path.last().unwrap().unwrap();
|
||||||
|
|
||||||
|
let dist = match last_node.electric_pole_type {
|
||||||
|
ElectricPoleType::Small => 7,
|
||||||
|
ElectricPoleType::Medium => 9,
|
||||||
|
ElectricPoleType::Big => 6,
|
||||||
|
ElectricPoleType::Substation => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let r = roboportmap
|
||||||
|
.iter()
|
||||||
|
.position(|r| {
|
||||||
|
r.x.abs_diff(last_node.pos.x) <= dist
|
||||||
|
&& r.y.abs_diff(last_node.pos.y) <= dist
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let p = roboportmap.swap_remove(r);
|
||||||
|
visited_roboports.push(p);
|
||||||
|
} else {
|
||||||
|
panic!("No path found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use factorio_core::{misc::PositionMap, prelude::Position};
|
use factorio_core::{misc::PositionMap, prelude::Position};
|
||||||
use factorio_graph::{
|
use factorio_graph::{
|
||||||
graph::Graph,
|
graph::Graph,
|
||||||
|
|
@ -7,7 +9,7 @@ use factorio_graph::{
|
||||||
|
|
||||||
use crate::abstraction::Entity;
|
use crate::abstraction::Entity;
|
||||||
|
|
||||||
use super::Blueprint;
|
use super::{Blueprint, EntityType};
|
||||||
|
|
||||||
struct RoboportGraph<'a> {
|
struct RoboportGraph<'a> {
|
||||||
roboports: &'a [Position],
|
roboports: &'a [Position],
|
||||||
|
|
@ -60,7 +62,6 @@ impl Blueprint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg!(universe, sets.len());
|
|
||||||
let res = greedy_connected_set_cover_priority_queue::<_, _, FastBinaryHeap<_>>(
|
let res = greedy_connected_set_cover_priority_queue::<_, _, FastBinaryHeap<_>>(
|
||||||
universe,
|
universe,
|
||||||
&sets,
|
&sets,
|
||||||
|
|
@ -70,7 +71,11 @@ impl Blueprint {
|
||||||
);
|
);
|
||||||
|
|
||||||
for r in res {
|
for r in res {
|
||||||
|
if self.placeable(roboports[r], Position::new(8, 8)) {
|
||||||
self.add_entity(Entity::new_roboport(roboports[r]));
|
self.add_entity(Entity::new_roboport(roboports[r]));
|
||||||
|
} else {
|
||||||
|
panic!("Roboport not placeable");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,10 @@ impl Color {
|
||||||
Self::new(0x0f, 0xf0, 0xfc)
|
Self::new(0x0f, 0xf0, 0xfc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn yellow() -> Self {
|
||||||
|
Self::new(0xff, 0xff, 0x00)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn gray(l: u8) -> Self {
|
pub fn gray(l: u8) -> Self {
|
||||||
Self::new(l, l, l)
|
Self::new(l, l, l)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue