diff --git a/Cargo.lock b/Cargo.lock index 7c68c61..f8796c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -584,6 +584,21 @@ dependencies = [ "termcolor", ] +[[package]] +name = "factorio-layout" +version = "0.1.0" +dependencies = [ + "clap 4.5.26", + "factorio-core", + "factorio-pathfinding", + "image", + "miette", + "rand", + "serde", + "serde_json", + "serde_yaml", +] + [[package]] name = "factorio-pathfinding" version = "0.1.0" @@ -599,7 +614,6 @@ dependencies = [ "miette", "proptest", "proptest-derive", - "rand", "serde", "serde_json", "serde_yaml", diff --git a/Cargo.toml b/Cargo.toml index 69f0f0b..a96e4f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = [ "factorio-blueprint", "factorio-blueprint-generator", "factorio-core", +members = [ "factorio-blueprint", "factorio-blueprint-generator", "factorio-core", "factorio-layout", "factorio-pathfinding" ] resolver = "2" diff --git a/factorio-blueprint-generator/src/bin/multistation.rs b/factorio-blueprint-generator/src/bin/multistation.rs index c40b4f3..79647f5 100644 --- a/factorio-blueprint-generator/src/bin/multistation.rs +++ b/factorio-blueprint-generator/src/bin/multistation.rs @@ -85,6 +85,7 @@ fn main() { // ], 8, ) + .0 .to_blueprint(), ); diff --git a/factorio-blueprint-generator/src/multistation.rs b/factorio-blueprint-generator/src/multistation.rs index c97e292..4b9676b 100644 --- a/factorio-blueprint-generator/src/multistation.rs +++ b/factorio-blueprint-generator/src/multistation.rs @@ -40,7 +40,10 @@ fn calculate_station_height( station_height } -pub fn multistation(stations: &[StationSpec], stacker_size: usize) -> Blueprint { +pub fn multistation( + stations: &[StationSpec], + stacker_size: usize, +) -> (Blueprint, PositionType, Vec) { let longest_train = stations .iter() .map(|s| s.locomotives + s.wagons) @@ -144,6 +147,7 @@ pub fn multistation(stations: &[StationSpec], stacker_size: usize) -> Blueprint let inrail_x = 10 - 4 * stacker_length as PositionType; let outrail_x = inrail_x + 52 + 4 * (7 * longest_train).div_ceil(2) as PositionType; + let mut output_heights = Vec::new(); let mut previous_station_heights = 0; // station for (i, station) in stations.iter().enumerate() { @@ -269,6 +273,8 @@ pub fn multistation(stations: &[StationSpec], stacker_size: usize) -> Blueprint let station_height = calculate_station_height(output_height, station.lanes, station.beltspeed); + output_heights.push(30 + total_stacker_height + previous_station_heights + output_height); + // rail crossing let (beltdirection, underground_left, underground_right) = match station.load { true => ( @@ -629,5 +635,5 @@ pub fn multistation(stations: &[StationSpec], stacker_size: usize) -> Blueprint blueprint.transform(Transformation::new(Direction::Right, Position::new(0, 0))); - blueprint + (blueprint, outrail_x + 5, output_heights) } diff --git a/factorio-blueprint/src/abstraction.rs b/factorio-blueprint/src/abstraction.rs index c8f57be..0296ea4 100644 --- a/factorio-blueprint/src/abstraction.rs +++ b/factorio-blueprint/src/abstraction.rs @@ -1,9 +1,5 @@ use factorio_core::{ - aabb::AABB, - beltoptions::Beltspeed, - direction, - pathfield::PathField, - prelude::{Direction, Position, PositionType, Transformable, Transformation}, + aabb::AABB, beltoptions::Beltspeed, pathfield::PathField, prelude::*, quaterdirection::QuaterDirection, }; use std::{collections::HashMap, sync::atomic::AtomicUsize}; diff --git a/factorio-layout/Cargo.toml b/factorio-layout/Cargo.toml new file mode 100644 index 0000000..9ab3d09 --- /dev/null +++ b/factorio-layout/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "factorio-layout" +version = "0.1.0" +edition = "2024" + +[dependencies] +factorio-core = { path = "../factorio-core" } +factorio-pathfinding = { path = "../factorio-pathfinding" } +rand = { version = "0.8.5", features = ["small_rng"] } +serde = { version = "1.0.192", features = ["derive"] } +image = "0.25.2" +serde_json = "1.0.108" +clap = { version = "4.4.8", features = ["derive"] } +miette = { version = "7.2.0", features = ["fancy"] } +serde_yaml = "0.9.34" diff --git a/factorio-pathfinding/layout.yml b/factorio-layout/layout.yml similarity index 100% rename from factorio-pathfinding/layout.yml rename to factorio-layout/layout.yml diff --git a/factorio-pathfinding/layout2.yml b/factorio-layout/layout2.yml similarity index 100% rename from factorio-pathfinding/layout2.yml rename to factorio-layout/layout2.yml diff --git a/factorio-pathfinding/layout3.yml b/factorio-layout/layout3.yml similarity index 100% rename from factorio-pathfinding/layout3.yml rename to factorio-layout/layout3.yml diff --git a/factorio-pathfinding/src/bin/layout.rs b/factorio-layout/src/bin/layout.rs similarity index 95% rename from factorio-pathfinding/src/bin/layout.rs rename to factorio-layout/src/bin/layout.rs index 151161c..e8ab767 100644 --- a/factorio-pathfinding/src/bin/layout.rs +++ b/factorio-layout/src/bin/layout.rs @@ -1,8 +1,8 @@ use clap::{Parser, Subcommand}; use factorio_core::visualize::Visualize; -use factorio_pathfinding::layout::{genetic_algorithm2, GeneticAlgorithm, PathLayout}; +use factorio_layout::layout::{GeneticAlgorithm, PathLayout, genetic_algorithm2}; use miette::{Context, IntoDiagnostic, Result}; -use rand::{rngs::SmallRng, SeedableRng}; +use rand::{SeedableRng, rngs::SmallRng}; use std::path::PathBuf; #[derive(Debug, Parser)] diff --git a/factorio-pathfinding/src/layout/mod.rs b/factorio-layout/src/layout.rs similarity index 90% rename from factorio-pathfinding/src/layout/mod.rs rename to factorio-layout/src/layout.rs index 5bd6d38..8a4a7bc 100644 --- a/factorio-pathfinding/src/layout/mod.rs +++ b/factorio-layout/src/layout.rs @@ -1,10 +1,10 @@ -use crate::belt_finding::conflict_avoidance::ConflictAvoidance; use factorio_core::{ pathfield::PathField, prelude::*, - visualize::{image_grid, Color, Symbol, Visualization, Visualize}, + visualize::{Color, Symbol, Visualization, Visualize, image_grid}, }; -use rand::{seq::SliceRandom, Rng}; +use factorio_pathfinding::belt_finding::{self, conflict_avoidance::ConflictAvoidance}; +use rand::{Rng, seq::SliceRandom}; use serde::{Deserialize, Serialize}; use std::{sync::atomic::AtomicU32, time::Instant}; @@ -195,9 +195,48 @@ pub struct PathLayout<'a> { score: usize, } +pub fn beltfinding_problem_from_layout(l: &Layout) -> belt_finding::Problem { + let mut p = belt_finding::Problem::new(l.problem.size.x as usize, l.problem.size.y as usize); + + for b in &l.blocks { + let aabb = b.get_aabb(); + + p.set_blocked_range( + aabb.min().x as usize, + aabb.min().y as usize, + aabb.max().x as usize, + aabb.max().y as usize, + true, + ); + } + + for c in &l.problem.connections { + let start_transform = l.blocks[c.startblock].block_to_world(); + let startpos = l.problem.blocks[c.startblock].output[c.startpoint] + .offset + .transform(start_transform); + let startdir = l.problem.blocks[c.startblock].output[c.startpoint] + .dir + .transform(start_transform); + let end_transform = l.blocks[c.endblock].block_to_world(); + let endpos = l.problem.blocks[c.endblock].input[c.endpoint] + .offset + .transform(end_transform); + let enddir = l.problem.blocks[c.endblock].input[c.endpoint] + .dir + .transform(end_transform); + p.add_connection( + (startpos, startdir), + (endpos.in_direction(&enddir, -1), enddir), + ); + } + + p +} + impl<'a> PathLayout<'a> { pub fn new(layout: Layout<'a>) -> Option> { - let mut p = crate::belt_finding::Problem::from_layout(&layout); + let mut p = beltfinding_problem_from_layout(&layout); if !p.find_path() { return None; @@ -343,7 +382,7 @@ impl Layout<'_> { let b = &problem.blocks[blocks.len()]; for _ in 0..1000 { - let dir = rng.gen::(); + let dir = rng.r#gen::(); let pos = match dir { Direction::Up => Position::new( @@ -433,7 +472,7 @@ impl Layout<'_> { fn mutate_replace(layout: &mut Layout, rng: &mut R) -> bool { let i = rng.gen_range(0..layout.blocks.len()); - let dir = rng.gen::(); + let dir = rng.r#gen::(); let b = &layout.problem.blocks[i]; @@ -492,7 +531,7 @@ impl Layout<'_> { fn mutate_jiggle(layout: &mut Layout, rng: &mut R) -> bool { let i = rng.gen_range(0..layout.blocks.len()); - let dir = rng.gen::(); + let dir = rng.r#gen::(); let step = [(1, 10), (2, 5), (3, 5)] .choose_weighted(rng, |i| i.1) .unwrap() diff --git a/factorio-layout/src/lib.rs b/factorio-layout/src/lib.rs new file mode 100644 index 0000000..dd64619 --- /dev/null +++ b/factorio-layout/src/lib.rs @@ -0,0 +1 @@ +pub mod layout; diff --git a/factorio-pathfinding/Cargo.toml b/factorio-pathfinding/Cargo.toml index c9e3dcf..243a788 100644 --- a/factorio-pathfinding/Cargo.toml +++ b/factorio-pathfinding/Cargo.toml @@ -24,7 +24,6 @@ image = "0.25.2" miette = { version = "7.2.0", features = ["fancy"] } proptest = "1.5.0" proptest-derive = "0.5.0" -rand = { version = "0.8.5", features = ["small_rng"] } serde = { version = "1.0.192", features = ["derive"] } serde_json = "1.0.108" serde_yaml = "0.9.34" diff --git a/factorio-pathfinding/src/belt_finding/mod.rs b/factorio-pathfinding/src/belt_finding/mod.rs index 9136ebf..2b8a4dd 100644 --- a/factorio-pathfinding/src/belt_finding/mod.rs +++ b/factorio-pathfinding/src/belt_finding/mod.rs @@ -1,6 +1,5 @@ use crate::graph::wheighted_graph::shortest_path::dijkstra; use crate::graph::wheighted_graph::WheightedGraph; -use crate::layout::Layout; use crate::misc::Map; use crate::priority_queue::BinaryHeap; use factorio_core::{prelude::*, visualize::Visualize}; @@ -34,44 +33,44 @@ impl Problem { } } - pub fn from_layout(l: &Layout) -> Self { - let mut p = Self::new(l.problem.size.x as usize, l.problem.size.y as usize); + // pub fn from_layout(l: &Layout) -> Self { + // let mut p = Self::new(l.problem.size.x as usize, l.problem.size.y as usize); - for b in &l.blocks { - let aabb = b.get_aabb(); + // for b in &l.blocks { + // let aabb = b.get_aabb(); - p.set_blocked_range( - aabb.min().x as usize, - aabb.min().y as usize, - aabb.max().x as usize, - aabb.max().y as usize, - true, - ); - } + // p.set_blocked_range( + // aabb.min().x as usize, + // aabb.min().y as usize, + // aabb.max().x as usize, + // aabb.max().y as usize, + // true, + // ); + // } - for c in &l.problem.connections { - let start_transform = l.blocks[c.startblock].block_to_world(); - let startpos = l.problem.blocks[c.startblock].output[c.startpoint] - .offset - .transform(start_transform); - let startdir = l.problem.blocks[c.startblock].output[c.startpoint] - .dir - .transform(start_transform); - let end_transform = l.blocks[c.endblock].block_to_world(); - let endpos = l.problem.blocks[c.endblock].input[c.endpoint] - .offset - .transform(end_transform); - let enddir = l.problem.blocks[c.endblock].input[c.endpoint] - .dir - .transform(end_transform); - p.add_connection( - (startpos, startdir), - (endpos.in_direction(&enddir, -1), enddir), - ); - } + // for c in &l.problem.connections { + // let start_transform = l.blocks[c.startblock].block_to_world(); + // let startpos = l.problem.blocks[c.startblock].output[c.startpoint] + // .offset + // .transform(start_transform); + // let startdir = l.problem.blocks[c.startblock].output[c.startpoint] + // .dir + // .transform(start_transform); + // let end_transform = l.blocks[c.endblock].block_to_world(); + // let endpos = l.problem.blocks[c.endblock].input[c.endpoint] + // .offset + // .transform(end_transform); + // let enddir = l.problem.blocks[c.endblock].input[c.endpoint] + // .dir + // .transform(end_transform); + // p.add_connection( + // (startpos, startdir), + // (endpos.in_direction(&enddir, -1), enddir), + // ); + // } - p - } + // p + // } pub fn add_connection(&mut self, start: (Position, Direction), end: (Position, Direction)) { self.start.push(start); diff --git a/factorio-pathfinding/src/lib.rs b/factorio-pathfinding/src/lib.rs index de710f8..13c2f56 100644 --- a/factorio-pathfinding/src/lib.rs +++ b/factorio-pathfinding/src/lib.rs @@ -1,5 +1,4 @@ pub mod belt_finding; pub mod graph; -pub mod layout; pub mod misc; pub mod priority_queue;