diff --git a/Cargo.lock b/Cargo.lock index b6bb6a3..698637e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -566,7 +566,9 @@ dependencies = [ "clap 4.5.27", "factorio-blueprint", "factorio-core", + "factorio-layout", "factorio-pathfinding", + "rand", "serde_json", ] diff --git a/factorio-blueprint-generator/Cargo.toml b/factorio-blueprint-generator/Cargo.toml index 8ac54ed..ecd7d55 100644 --- a/factorio-blueprint-generator/Cargo.toml +++ b/factorio-blueprint-generator/Cargo.toml @@ -5,7 +5,9 @@ edition = "2024" [dependencies] factorio-pathfinding = { path = "../factorio-pathfinding" } +factorio-layout = { path = "../factorio-layout" } factorio-core = { path = "../factorio-core" } factorio-blueprint = { path = "../factorio-blueprint" } serde_json = "1.0.135" clap = { version = "4.5.26", features = ["derive"] } +rand = { version = "0.8.5", features = ["small_rng"] } diff --git a/factorio-blueprint-generator/src/assembly.rs b/factorio-blueprint-generator/src/assembly.rs index 2847080..4b11f7e 100644 --- a/factorio-blueprint-generator/src/assembly.rs +++ b/factorio-blueprint-generator/src/assembly.rs @@ -28,7 +28,7 @@ pub fn assembly_line(assembly_machines: usize) -> Blueprint { for i in 0..assembly_machines { blueprint.add_entity(Entity::new_production( "assembling-machine-3", - "iron-gears", + "iron-gear-wheel", Position::new(3 + 6 * i as PositionType, 9), Direction::Up, Position::new(6, 6), diff --git a/factorio-blueprint-generator/src/bin/generate_factory.rs b/factorio-blueprint-generator/src/bin/generate_factory.rs new file mode 100644 index 0000000..7ed9ffe --- /dev/null +++ b/factorio-blueprint-generator/src/bin/generate_factory.rs @@ -0,0 +1,39 @@ +use clap::Parser; +use factorio_blueprint::{BlueprintString, encode}; +use factorio_blueprint_generator::factory::generate_factory; +use factorio_core::prelude::*; +use factorio_layout::valid_layout::ValidLayout; +use factorio_pathfinding::belt_finding::ConflictAvoidance; +use rand::{SeedableRng, rngs::SmallRng}; + +#[derive(Parser)] +struct Args { + #[arg(default_value_t = 0)] + seed: u64, + #[arg(short, long)] + json: bool, +} + +fn main() { + let args = Args::parse(); + + let l = ValidLayout { + max_tries: 10, + retries: 10, + start_size: Position::new(100, 100), + growth: Position::new(5, 5), + }; + let p = ConflictAvoidance { + timeout: Some(std::time::Duration::from_millis(20)), + }; + + let mut rng = SmallRng::seed_from_u64(args.seed); + + let b = BlueprintString::Blueprint(generate_factory(&l, &p, &mut rng).to_blueprint()); + + if args.json { + println!("{}", serde_json::to_string_pretty(&b).unwrap()); + } + + println!("{}", encode(&serde_json::to_string(&b).unwrap())); +} diff --git a/factorio-blueprint-generator/src/factory.rs b/factorio-blueprint-generator/src/factory.rs new file mode 100644 index 0000000..01e78f3 --- /dev/null +++ b/factorio-blueprint-generator/src/factory.rs @@ -0,0 +1,122 @@ +use factorio_blueprint::abstraction::Blueprint; +use factorio_core::{beltoptions::Beltspeed, prelude::*}; +use factorio_layout::{Connection, Interface, LayoutInput, Layouter, MacroBlock}; +use factorio_pathfinding::Pathfinder; +use rand::Rng; + +use crate::assembly::assembly_line; + +pub fn generate_factory( + layouter: &L, + pathfinder: &P, + rng: &mut impl Rng, +) -> Blueprint { + // 2 * gears + // 3 * copper wires + // 2 * green circuits + // 2 * inserter + let input = vec![ + Interface { + offset: Position::new(0, 1), + dir: Direction::Right, + }, + Interface { + offset: Position::new(0, 7), + dir: Direction::Right, + }, + Interface { + offset: Position::new(0, 8), + dir: Direction::Right, + }, + ]; + let output = vec![Interface { + offset: Position::new(0, 0), + dir: Direction::Left, + }]; + let blocks = vec![ + MacroBlock { + size: Position::new(6, 9), + input: input.clone(), + output: output.clone(), + }, + MacroBlock { + size: Position::new(9, 9), + input: input.clone(), + output: output.clone(), + }, + MacroBlock { + size: Position::new(6, 9), + input: input.clone(), + output: output.clone(), + }, + MacroBlock { + size: Position::new(6, 9), + input: input.clone(), + output: output.clone(), + }, + ]; + + let connections = vec![ + Connection { + startblock: 0, + startpoint: 0, + endblock: 3, + endpoint: 0, + lanes: 1, + beltspeed: Beltspeed::Fast, + }, + Connection { + startblock: 1, + startpoint: 0, + endblock: 2, + endpoint: 0, + lanes: 1, + beltspeed: Beltspeed::Fast, + }, + Connection { + startblock: 2, + startpoint: 0, + endblock: 3, + endpoint: 1, + lanes: 1, + beltspeed: Beltspeed::Fast, + }, + ]; + + let l = layouter + .layout( + &LayoutInput { + blocks, + connections, + }, + pathfinder, + rng, + ) + .unwrap(); + + let blueprints = vec![ + assembly_line(2), + assembly_line(3), + assembly_line(2), + assembly_line(2), + ]; + + let mut b = Blueprint::new(); + for (block, mut assembly_blueprint) in l.positions.iter().zip(blueprints) { + let offset = match block.dir() { + Direction::Up => Position::new(0, 0), + Direction::Right => Position::new(2, 0), + Direction::Down => Position::new(2, 2), + Direction::Left => Position::new(0, 2), + }; + assembly_blueprint.transform(Transformation::new(block.dir(), offset + 2 * block.pos())); + + b.add_blueprint(assembly_blueprint); + } + + for path in &l.path_result { + b.add_path(&path[1..], Beltspeed::Fast); + } + + b +} diff --git a/factorio-blueprint-generator/src/lib.rs b/factorio-blueprint-generator/src/lib.rs index 0c2db0a..0233643 100644 --- a/factorio-blueprint-generator/src/lib.rs +++ b/factorio-blueprint-generator/src/lib.rs @@ -1,6 +1,7 @@ pub mod assembly; pub mod balancer; pub mod binary_merger; +pub mod factory; pub mod multistation; pub mod station; pub mod train; diff --git a/factorio-layout/new_layout.yaml b/factorio-layout/new_layout.yaml index 0b7eb88..c35d5cf 100644 --- a/factorio-layout/new_layout.yaml +++ b/factorio-layout/new_layout.yaml @@ -39,7 +39,7 @@ connections: startpoint: 0 endblock: 0 endpoint: 0 - lanes: 1 + lanes: 2 beltspeed: Normal - startblock: 0 startpoint: 0 diff --git a/factorio-layout/new_layout3.yml b/factorio-layout/new_layout3.yml new file mode 100644 index 0000000..593232a --- /dev/null +++ b/factorio-layout/new_layout3.yml @@ -0,0 +1,127 @@ +size: + x: 50 + y: 50 +blocks: + - size: + x: 3 + y: 2 + input: + - offset: + x: 1 + y: 1 + dir: Up + output: + - offset: + x: 1 + y: 0 + dir: Up + - size: + x: 5 + y: 2 + input: + output: + - offset: + x: 1 + y: 1 + dir: Down + - size: + x: 5 + y: 7 + input: + - offset: + x: 0 + y: 1 + dir: Right + output: + - size: + x: 5 + y: 5 + input: + - offset: + x: 0 + y: 1 + dir: Right + output: + - offset: + x: 0 + y: 3 + dir: Left + - size: + x: 10 + y: 10 + input: + - offset: + x: 0 + y: 1 + dir: Right + - offset: + x: 0 + y: 3 + dir: Right + output: + - offset: + x: 9 + y: 1 + dir: Right + - offset: + x: 9 + y: 3 + dir: Right + - size: + x: 10 + y: 5 + input: + - offset: + x: 0 + y: 1 + dir: Right + - offset: + x: 0 + y: 3 + dir: Right + output: + - offset: + x: 9 + y: 1 + dir: Right + - offset: + x: 9 + y: 3 + dir: Right +connections: + - startblock: 1 + startpoint: 0 + endblock: 0 + endpoint: 0 + lanes: 2 + beltspeed: Normal + - startblock: 0 + startpoint: 0 + endblock: 3 + endpoint: 0 + lanes: 1 + beltspeed: Normal + - startblock: 3 + startpoint: 0 + endblock: 4 + endpoint: 0 + lanes: 1 + beltspeed: Normal + - startblock: 4 + startpoint: 0 + endblock: 5 + endpoint: 0 + lanes: 1 + beltspeed: Normal + - startblock: 4 + startpoint: 1 + endblock: 5 + endpoint: 1 + lanes: 1 + beltspeed: Normal + - startblock: 5 + startpoint: 0 + endblock: 2 + endpoint: 0 + lanes: 1 + beltspeed: Normal diff --git a/factorio-layout/src/bin/new_layout.rs b/factorio-layout/src/bin/new_layout.rs index 0757be3..6c0a4be 100644 --- a/factorio-layout/src/bin/new_layout.rs +++ b/factorio-layout/src/bin/new_layout.rs @@ -31,12 +31,12 @@ fn main() { }; let p = ConflictAvoidance { - timeout: Some(std::time::Duration::from_millis(100)), + timeout: Some(std::time::Duration::from_millis(5)), }; let mut rng = SmallRng::seed_from_u64(args.seed); let r = l.layout(&problem, &p, &mut rng); - dbg!(r); + // dbg!(r); } diff --git a/factorio-layout/src/layout.rs b/factorio-layout/src/layout.rs index 8a4a7bc..9dc2109 100644 --- a/factorio-layout/src/layout.rs +++ b/factorio-layout/src/layout.rs @@ -152,20 +152,20 @@ pub fn valid_path_layout<'a, R: Rng + ?Sized>( } } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub(crate) struct MacroBlock { pub(crate) size: Position, pub(crate) input: Vec, pub(crate) output: Vec, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone, Copy)] pub(crate) struct Interface { pub(crate) offset: Position, pub(crate) dir: Direction, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone, Copy)] pub(crate) struct Connection { pub(crate) startblock: usize, pub(crate) startpoint: usize, @@ -173,7 +173,7 @@ pub(crate) struct Connection { pub(crate) endpoint: usize, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct Problem { pub(crate) size: Position, pub(crate) blocks: Vec, diff --git a/factorio-layout/src/lib.rs b/factorio-layout/src/lib.rs index 7368c99..ea67ffa 100644 --- a/factorio-layout/src/lib.rs +++ b/factorio-layout/src/lib.rs @@ -3,21 +3,20 @@ use factorio_pathfinding::Pathfinder; use rand::Rng; use serde::{Deserialize, Serialize}; -pub mod block; pub mod genetic_algorithm_v1; pub mod genetic_algorithm_v2; pub mod layout; pub mod misc; pub mod valid_layout; -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct MacroBlock { pub size: Position, pub input: Vec, pub output: Vec, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone, Copy)] pub struct Interface { pub offset: Position, pub dir: Direction, diff --git a/factorio-pathfinding/src/belt_finding/conflict_avoidance.rs b/factorio-pathfinding/src/belt_finding/conflict_avoidance.rs index 7e91083..4160145 100644 --- a/factorio-pathfinding/src/belt_finding/conflict_avoidance.rs +++ b/factorio-pathfinding/src/belt_finding/conflict_avoidance.rs @@ -267,7 +267,7 @@ impl ConflictAvoidance { while b.next_finish_state(timeout) { // println!("{}", b); // b.print(); - b.print_visualization(); + // b.print_visualization(); let c = b.cost(); if c < min_cost { min_cost = c; diff --git a/factorio-pathfinding/src/belt_finding/mod.rs b/factorio-pathfinding/src/belt_finding/mod.rs index 103380c..9cd950c 100644 --- a/factorio-pathfinding/src/belt_finding/mod.rs +++ b/factorio-pathfinding/src/belt_finding/mod.rs @@ -40,13 +40,14 @@ impl SinglePathfinder for ConflictAvoidance { ); } - p.print_visualization(); + // p.print_visualization(); if p.find_path() { let mut c = conflict_avoidance::ConflictAvoidance::new(&p); - c.print_visualization(); + // c.print_visualization(); if c.remove_all_conflicts(self.timeout) { + c.print_visualization(); Some(c.get_paths().to_vec()) } else { None diff --git a/factorio-pathfinding/src/lib.rs b/factorio-pathfinding/src/lib.rs index 965beea..80af563 100644 --- a/factorio-pathfinding/src/lib.rs +++ b/factorio-pathfinding/src/lib.rs @@ -64,7 +64,7 @@ where start_dir: c.start_dir, end_pos: c .end_pos - .in_direction(&c.start_dir.clockwise(), i as PositionType), + .in_direction(&c.end_dir.clockwise(), i as PositionType), end_dir: c.end_dir, beltspeed: c.beltspeed, })