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_roboport_network();
|
||||
b.print_visualization();
|
||||
b.connect_roboport_power();
|
||||
|
||||
b.print_visualization();
|
||||
b.connect_power_networks();
|
||||
|
||||
b
|
||||
|
|
|
|||
|
|
@ -441,7 +441,7 @@ impl Entity {
|
|||
}
|
||||
}
|
||||
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(
|
||||
(self.position + Position::new(dx, dy)) / 2 + offset,
|
||||
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::{
|
||||
graph::Graph,
|
||||
priority_queue::binary_heap::FastBinaryHeap,
|
||||
wheighted_graph::{WheightedGraph, steiner_tree},
|
||||
wheighted_graph::{WheightedGraph, shortest_path::dijkstra, steiner_tree},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
|
@ -155,16 +159,6 @@ impl Blueprint {
|
|||
|
||||
if let Some(cost) = cost {
|
||||
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();
|
||||
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_graph::{
|
||||
graph::Graph,
|
||||
|
|
@ -7,7 +9,7 @@ use factorio_graph::{
|
|||
|
||||
use crate::abstraction::Entity;
|
||||
|
||||
use super::Blueprint;
|
||||
use super::{Blueprint, EntityType};
|
||||
|
||||
struct RoboportGraph<'a> {
|
||||
roboports: &'a [Position],
|
||||
|
|
@ -60,7 +62,6 @@ impl Blueprint {
|
|||
}
|
||||
}
|
||||
|
||||
dbg!(universe, sets.len());
|
||||
let res = greedy_connected_set_cover_priority_queue::<_, _, FastBinaryHeap<_>>(
|
||||
universe,
|
||||
&sets,
|
||||
|
|
@ -70,7 +71,11 @@ impl Blueprint {
|
|||
);
|
||||
|
||||
for r in res {
|
||||
self.add_entity(Entity::new_roboport(roboports[r]));
|
||||
if self.placeable(roboports[r], Position::new(8, 8)) {
|
||||
self.add_entity(Entity::new_roboport(roboports[r]));
|
||||
} else {
|
||||
panic!("Roboport not placeable");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,10 @@ impl Color {
|
|||
Self::new(0x0f, 0xf0, 0xfc)
|
||||
}
|
||||
|
||||
pub fn yellow() -> Self {
|
||||
Self::new(0xff, 0xff, 0x00)
|
||||
}
|
||||
|
||||
pub fn gray(l: u8) -> Self {
|
||||
Self::new(l, l, l)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue