Compare commits

...

2 commits

Author SHA1 Message Date
b4ab291884 Improve power connection 2025-03-04 21:17:21 +01:00
2f637e1a82 Move graph example to correct crate 2025-03-04 21:16:25 +01:00
3 changed files with 52 additions and 21 deletions

View file

@ -1,12 +1,11 @@
use std::path::PathBuf;
use clap::Parser; use clap::Parser;
use factorio_blueprint::{BlueprintString, encode}; use factorio_blueprint::{BlueprintString, encode};
use factorio_blueprint_generator::factory::{FactoryGraph, generate_factory}; use factorio_blueprint_generator::factory::{FactoryGraph, generate_factory};
use factorio_core::prelude::*; use factorio_core::{prelude::*, visualize::Visualize};
use factorio_layout::{genetic_algorithm_v1::GeneticAlgorithm, valid_layout::ValidLayout}; use factorio_layout::{genetic_algorithm_v1::GeneticAlgorithm, valid_layout::ValidLayout};
use factorio_pathfinding::belt_finding::ConflictAvoidance; use factorio_pathfinding::belt_finding::ConflictAvoidance;
use rand::{SeedableRng, rngs::SmallRng}; use rand::{SeedableRng, rngs::SmallRng};
use std::path::PathBuf;
#[derive(Parser)] #[derive(Parser)]
struct Args { struct Args {
@ -25,7 +24,7 @@ fn main() {
// .with_env_filter(EnvFilter::from_default_env()) // .with_env_filter(EnvFilter::from_default_env())
// .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE) // .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
// .init(); // .init();
tracing_perfetto::install_perfetto_subscriber(); // tracing_perfetto::install_perfetto_subscriber();
let text = std::fs::File::open(&args.path).unwrap(); let text = std::fs::File::open(&args.path).unwrap();
let factory_graph: FactoryGraph = serde_yaml::from_reader(text).unwrap(); let factory_graph: FactoryGraph = serde_yaml::from_reader(text).unwrap();
@ -41,10 +40,10 @@ fn main() {
let l = GeneticAlgorithm { let l = GeneticAlgorithm {
mutation_retries: 20, mutation_retries: 20,
population_size: 4, population_size: 10,
population_keep: 1, population_keep: 2,
population_new: 1, population_new: 2,
generations: 5, generations: 4,
valid_layout: l, valid_layout: l,
}; };
let p = ConflictAvoidance { let p = ConflictAvoidance {
@ -53,9 +52,11 @@ fn main() {
let mut rng = SmallRng::seed_from_u64(args.seed); let mut rng = SmallRng::seed_from_u64(args.seed);
let b = BlueprintString::Blueprint( let b = generate_factory(&l, &p, factory_graph, &mut rng);
generate_factory(&l, &p, factory_graph, &mut rng).to_blueprint(),
); b.print_visualization();
let b = BlueprintString::Blueprint(b.to_blueprint());
if args.json { if args.json {
println!("{}", serde_json::to_string_pretty(&b).unwrap()); println!("{}", serde_json::to_string_pretty(&b).unwrap());

View file

@ -8,14 +8,35 @@ use super::*;
#[derive(Debug)] #[derive(Debug)]
struct PowerGraph { struct PowerGraph {
nodes: HashMap<Position, Vec<(Position, f64)>>, nodes: HashMap<Position, (Vec<Position>, f64)>,
}
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
enum NodeType {
In,
Out,
} }
impl WheightedGraph for PowerGraph { impl WheightedGraph for PowerGraph {
type Node = Position; type Node = (Position, NodeType);
fn edge(&self, node: &Self::Node, num: usize) -> Option<(Self::Node, f64)> { fn edge(&self, node: &Self::Node, num: usize) -> Option<(Self::Node, f64)> {
self.nodes.get(node).and_then(|v| v.get(num).cloned()) match node.1 {
NodeType::In => {
if num == 0 {
self.nodes
.get(&node.0)
.map(|v| ((node.0, NodeType::Out), v.1))
} else {
None
}
}
NodeType::Out => self
.nodes
.get(&node.0)
.and_then(|v| v.0.get(num).cloned())
.map(|v| ((v, NodeType::In), 0.0)),
}
} }
} }
@ -59,7 +80,7 @@ impl Blueprint {
for y_source in 0..blocked.height { for y_source in 0..blocked.height {
for x_source in 0..blocked.width { for x_source in 0..blocked.width {
if blocked.get(x_source, y_source).is_some() { if let &Some(w) = blocked.get(x_source, y_source) {
let pos = Position::new(x_source as PositionType, y_source as PositionType); let pos = Position::new(x_source as PositionType, y_source as PositionType);
let mut edges = Vec::new(); let mut edges = Vec::new();
for (xx, yy) in (-9..=9) for (xx, yy) in (-9..=9)
@ -77,11 +98,11 @@ impl Blueprint {
}) })
{ {
if let &Some(w) = blocked.get(xx, yy) { if let &Some(w) = blocked.get(xx, yy) {
edges.push((Position::new(xx as PositionType, yy as PositionType), w)); edges.push(Position::new(xx as PositionType, yy as PositionType));
} }
} }
if !edges.is_empty() { if !edges.is_empty() {
graph.nodes.insert(pos, edges); graph.nodes.insert(pos, (edges, w));
} }
} }
} }
@ -89,7 +110,12 @@ impl Blueprint {
let pole_positions = power_poles let pole_positions = power_poles
.iter() .iter()
.map(|(_, e)| (e.position - Position::new(1, 1)) / 2 + offset) .map(|(_, e)| {
(
(e.position - Position::new(1, 1)) / 2 + offset,
NodeType::Out,
)
})
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if let Some(res) = if let Some(res) =
@ -101,7 +127,11 @@ impl Blueprint {
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
for path in res { for path in res {
for &p in &path { let path_iter = path.iter().filter_map(|(p, n)| match n {
NodeType::In => None,
NodeType::Out => Some(p),
});
for &p in path_iter.clone() {
match power_pole_map.entry(p) { match power_pole_map.entry(p) {
std::collections::hash_map::Entry::Occupied(_occupied_entry) => (), std::collections::hash_map::Entry::Occupied(_occupied_entry) => (),
std::collections::hash_map::Entry::Vacant(vacant_entry) => { std::collections::hash_map::Entry::Vacant(vacant_entry) => {
@ -113,7 +143,7 @@ impl Blueprint {
} }
} }
} }
for (p, n) in path.iter().zip(path[1..].iter()) { 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); self.add_wire(power_pole_map[n], 5, power_pole_map[p], 5);
} }
} }

View file

@ -1,4 +1,4 @@
use factorio_pathfinding::priority_queue::{fibonacci_heap::FibonacciHeap, PriorityQueue}; use factorio_graph::priority_queue::{PriorityQueue, fibonacci_heap::FibonacciHeap};
use std::fmt::Debug; use std::fmt::Debug;
fn test_loop<P>() fn test_loop<P>()