diff --git a/factorio-blueprint-generator/factory_graph_inserter.yml b/factorio-blueprint-generator/factory_graph_inserter.yml index 7e5e2cb..1d00af3 100644 --- a/factorio-blueprint-generator/factory_graph_inserter.yml +++ b/factorio-blueprint-generator/factory_graph_inserter.yml @@ -1,49 +1,58 @@ subfactories: - !SubFactory recipe: iron-gear-wheel - machines: 2 + machines: 6 machine: assembly-machine-3 - !SubFactory recipe: copper-cable - machines: 3 + machines: 9 machine: assembly-machine-3 - !SubFactory recipe: electronic-circuit - machines: 2 + machines: 6 machine: assembly-machine-3 - !SubFactory recipe: inserter - machines: 2 + machines: 6 machine: assembly-machine-3 - !ExternalConnection inputs: 1 outputs: 5 + - !SideLoader factory_connections: - item: iron-gear-wheel - amount: 5 - from: 0 - to: 3 - - item: copper-cable amount: 15 + from: 0 + to: 5 + - item: copper-cable + amount: 45 from: 1 to: 2 - - item: electronic-circuit - amount: 5 - from: 2 - to: 3 - item: iron-plate - amount: 10 + amount: 30 from: 4 to: 0 - item: iron-plate - amount: 5 + amount: 15 from: 4 to: 2 - item: copper-plate - amount: 7.5 + amount: 22.5 from: 4 to: 1 - item: inserter - amount: 5 + amount: 15 from: 3 to: 4 + - item: iron-plate + amount: 15 + from: 4 + to: 5 + - item: iron-plate;iron-gear-wheel + amount: 30 + from: 5 + to: 3 + - item: electronic-circuit + amount: 15 + from: 2 + to: 3 diff --git a/factorio-blueprint-generator/src/assembly.rs b/factorio-blueprint-generator/src/assembly.rs index ae7968e..2b1d440 100644 --- a/factorio-blueprint-generator/src/assembly.rs +++ b/factorio-blueprint-generator/src/assembly.rs @@ -415,7 +415,8 @@ pub fn assembly_line_2_input( Direction::Right, )); } - if i < (3 * halve_machines - 1) { + if i < (3 * halve_machines - 2) || (halve_machines % 3 == 1 && i < (3 * halve_machines - 1)) + { blueprint.add_entity(Entity::new_belt( output_belt, Position::new(1 + 2 * i as PositionType, 15), diff --git a/factorio-blueprint-generator/src/bin/generate_factory.rs b/factorio-blueprint-generator/src/bin/generate_factory.rs index 334fbd8..6200eee 100644 --- a/factorio-blueprint-generator/src/bin/generate_factory.rs +++ b/factorio-blueprint-generator/src/bin/generate_factory.rs @@ -29,16 +29,16 @@ fn main() { let l = ValidLayout { max_tries: 10, retries: 20, - start_size: Position::new(20, 20), - growth: Position::new(5, 5), + start_size: Position::new(48, 48), + growth: Position::new(0, 0), }; let l = GeneticAlgorithm { mutation_retries: 20, - population_size: 10, - population_keep: 2, + population_size: 20, + population_keep: 1, population_new: 2, - generations: 20, + generations: 50, valid_layout: l, }; let p = ConflictAvoidance { diff --git a/factorio-blueprint-generator/src/factory.rs b/factorio-blueprint-generator/src/factory.rs index 1e7c764..24138ed 100644 --- a/factorio-blueprint-generator/src/factory.rs +++ b/factorio-blueprint-generator/src/factory.rs @@ -1,4 +1,4 @@ -use factorio_blueprint::abstraction::Blueprint; +use factorio_blueprint::abstraction::{Blueprint, Entity}; use factorio_core::{beltoptions::Beltspeed, prelude::*}; use factorio_layout::{Connection, Interface, LayoutInput, Layouter, MacroBlock}; use factorio_pathfinding::Pathfinder; @@ -25,6 +25,7 @@ pub enum Building { outputs: usize, }, BeltPool, + SideLoader, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -46,7 +47,7 @@ pub fn generate_factory( let mut connections = Vec::new(); let mut used_connections = Vec::new(); - for b in &factory_graph.subfactories { + for (i, b) in factory_graph.subfactories.iter().enumerate() { match b { Building::SubFactory { recipe, @@ -55,12 +56,22 @@ pub fn generate_factory( } => { assert!(machine == "assembly-machine-3"); + let input_count = factory_graph + .factory_connections + .iter() + .filter(|&c| c.to == i) + .count(); + let (b, size, y_output, y_inputs) = assembly_line_2_input( *machines, recipe, - Beltspeed::Normal, - Some(Beltspeed::Normal), - Beltspeed::Normal, + Beltspeed::Express, + if input_count == 2 { + Some(Beltspeed::Express) + } else { + None + }, + Beltspeed::Express, ); blueprints.push(b); @@ -101,6 +112,34 @@ pub fn generate_factory( blueprints.push(Blueprint::new()); used_connections.push((0, 0)); } + Building::SideLoader => { + let mut blueprint = Blueprint::new(); + blueprint.add_entity(Entity::new_belt( + Beltspeed::Fast, + Position::new(1, 1), + Direction::Up, + )); + + blocks.push(MacroBlock { + size: Position::new(1, 1), + input: vec![ + Interface { + offset: Position::new(0, 0), + dir: Direction::Right, + }, + Interface { + offset: Position::new(0, 0), + dir: Direction::Left, + }, + ], + output: vec![Interface { + offset: Position::new(0, 0), + dir: Direction::Up, + }], + }); + blueprints.push(blueprint); + used_connections.push((0, 0)); + } Building::BeltPool => todo!(), } } @@ -112,7 +151,7 @@ pub fn generate_factory( endblock: c.to, endpoint: used_connections[c.to].1, lanes: 1, - beltspeed: Beltspeed::Normal, + beltspeed: Beltspeed::from_items_per_second(c.amount), }); used_connections[c.from].0 += 1; @@ -122,16 +161,11 @@ pub fn generate_factory( // dbg!(&blocks); // dbg!(&connections); - let l = layouter - .layout( - &LayoutInput { - blocks, - connections, - }, - pathfinder, - rng, - ) - .unwrap(); + let layout_input = LayoutInput { + blocks, + connections, + }; + let l = layouter.layout(&layout_input, pathfinder, rng).unwrap(); let mut b = Blueprint::new(); for (block, mut assembly_blueprint) in l.positions.iter().zip(blueprints) { @@ -146,8 +180,8 @@ pub fn generate_factory( b.add_blueprint(assembly_blueprint); } - for path in &l.path_result { - b.add_path(&path[1..], Beltspeed::Fast); + for (path, connection) in l.path_result.iter().zip(layout_input.connections.iter()) { + b.add_path(&path[1..], connection.beltspeed); } b diff --git a/factorio-core/src/beltoptions.rs b/factorio-core/src/beltoptions.rs index a181583..f13031a 100644 --- a/factorio-core/src/beltoptions.rs +++ b/factorio-core/src/beltoptions.rs @@ -56,6 +56,20 @@ impl Beltspeed { } s } + + pub fn from_items_per_second(x: f64) -> Self { + if x <= 15.0 { + Beltspeed::Normal + } else if x <= 30.0 { + Beltspeed::Fast + } else if x <= 45.0 { + Beltspeed::Express + } else if x <= 60.0 { + Beltspeed::Turbo + } else { + unreachable!() + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)] diff --git a/factorio-layout/src/genetic_algorithm_v1.rs b/factorio-layout/src/genetic_algorithm_v1.rs index cadfe2d..84160dd 100644 --- a/factorio-layout/src/genetic_algorithm_v1.rs +++ b/factorio-layout/src/genetic_algorithm_v1.rs @@ -31,10 +31,11 @@ impl Layouter for GeneticAlgorithm { } } } + population.sort_by_key(|(_, s)| *s); + + let mut best_result = population[0].clone(); for g in 0..self.generations { - population.sort_by_key(|(_, s)| *s); - for i in 0..(self.population_size - self.population_keep - self.population_new) { loop { let parent = &population[i % self.population_keep].0; @@ -71,11 +72,13 @@ impl Layouter for GeneticAlgorithm { } } + population.sort_by_key(|(_, s)| *s); + if population[0].1 < best_result.1 { + best_result = population[0].clone(); + } println!("completed generation {g}\nscore: {}", population[0].1); } - population.sort_by_key(|(_, s)| *s); - - population.into_iter().next().map(|(l, _)| l) + Some(best_result.0) } } diff --git a/factorio-layout/src/lib.rs b/factorio-layout/src/lib.rs index 74de956..6819ec7 100644 --- a/factorio-layout/src/lib.rs +++ b/factorio-layout/src/lib.rs @@ -38,7 +38,7 @@ pub struct LayoutInput { pub connections: Vec, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct LayoutResult { pub size: Position, pub positions: Vec,