Add automatic distribution

This commit is contained in:
hal8174 2025-03-31 23:28:18 +02:00
parent 721e83006d
commit aee56af22f
5 changed files with 386 additions and 14 deletions

View file

@ -0,0 +1,141 @@
subfactories:
- !SubFactory
recipe: chemical-science-pack
machines: 96
machine: assembly-machine-3
- !SubFactory
recipe: engine-unit
machines: 80
machine: assembly-machine-3
- !SubFactory
recipe: iron-gear-wheel
machines: 4
machine: assembly-machine-3
- !SubFactory
recipe: pipe
machines: 8
machine: assembly-machine-3
- !SubFactory
recipe: advanced-circuit
machines: 72
machine: assembly-machine-3
- !SubFactory
recipe: electronic-circuit
machines: 6
machine: assembly-machine-3
- !SubFactory
recipe: electronic-circuit
machines: 6
machine: assembly-machine-3
- !SubFactory
recipe: copper-cable
machines: 10
machine: assembly-machine-3
- !SubFactory
recipe: copper-cable
machines: 10
machine: assembly-machine-3
- !SubFactory
recipe: copper-cable
machines: 10
machine: assembly-machine-3
- !ExternalConnection
- !Distributor
- !Distributor
factory_connections:
- item: chemical-science-pack
amount: 10
from: 0
to: 10
- item: engine-unit
amount: 10
from: 1
to: 0
- item: advanced-circuit
amount: 15
from: 4
to: 0
- item: sulfur
amount: 5
from: 10
to: 0
- item: steel
amount: 10
from: 10
to: 1
- item: iron-gear-wheel
amount: 10
from: 2
to: 1
- item: pipe
amount: 20
from: 3
to: 1
- item: iron-plate
amount: 20
from: 10
to: 2
- item: iron-plate
amount: 20
from: 10
to: 3
- item: electronic-circuit
amount: 30
from: 12
to: 4
- item: electronic-circuit
amount: 15
from: 5
to: 12
- item: electronic-circuit
amount: 15
from: 6
to: 12
- item: plastic
amount: 30
from: 10
to: 4
- item: iron-plate
amount: 15
from: 10
to: 5
- item: iron-plate
amount: 15
from: 10
to: 6
- item: copper-plate
amount: 25
from: 10
to: 7
- item: copper-plate
amount: 25
from: 10
to: 8
- item: copper-plate
amount: 25
from: 10
to: 9
- item: copper-cable
amount: 45
from: 11
to: 5
- item: copper-cable
amount: 60
from: 11
to: 4
- item: copper-cable
amount: 50
from: 7
to: 11
- item: copper-cable
amount: 50
from: 8
to: 11
- item: copper-cable
amount: 45
from: 11
to: 6
- item: copper-cable
amount: 50
from: 9
to: 11

View file

@ -30,7 +30,7 @@ struct Args {
#[arg(short, long, default_value = "none")] #[arg(short, long, default_value = "none")]
tracing: Tracing, tracing: Tracing,
#[arg(long, default_value = "ca-fbh")] #[arg(long, default_value = "ca-bq")]
pathfinder: PathfinderArg, pathfinder: PathfinderArg,
} }

View file

@ -1,3 +1,7 @@
use crate::{
assembly::assembly_line_2_input,
multistation::{StationSpec, multistation},
};
use factorio_blueprint::abstraction::{Blueprint, Entity}; use factorio_blueprint::abstraction::{Blueprint, Entity};
use factorio_core::{beltoptions::Beltspeed, prelude::*, visualize::Visualize}; use factorio_core::{beltoptions::Beltspeed, prelude::*, visualize::Visualize};
use factorio_layout::{Connection, Interface, LayoutInput, Layouter, MacroBlock}; use factorio_layout::{Connection, Interface, LayoutInput, Layouter, MacroBlock};
@ -6,11 +10,6 @@ use rand::{Rng, SeedableRng};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use crate::{
assembly::assembly_line_2_input,
multistation::{StationSpec, multistation},
};
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FactoryGraph { pub struct FactoryGraph {
pub subfactories: Vec<Building>, pub subfactories: Vec<Building>,
@ -27,6 +26,7 @@ pub enum Building {
ExternalConnection, ExternalConnection,
Splitter, Splitter,
SideLoader, SideLoader,
Distributor,
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
@ -37,11 +37,13 @@ pub struct FactoryConnection {
pub to: usize, pub to: usize,
} }
#[derive(Debug)]
struct IntermediateConnection { struct IntermediateConnection {
input: HashMap<usize, IntermediateConnectionEntry>, input: HashMap<usize, IntermediateConnectionEntry>,
output: HashMap<usize, IntermediateConnectionEntry>, output: HashMap<usize, IntermediateConnectionEntry>,
} }
#[derive(Debug)]
struct IntermediateConnectionEntry { struct IntermediateConnectionEntry {
block: Option<usize>, block: Option<usize>,
interface: usize, interface: usize,
@ -446,6 +448,163 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
.collect::<HashMap<_, _>>(), .collect::<HashMap<_, _>>(),
}); });
} }
Building::Distributor => {
let mut blueprint = Blueprint::new();
blueprint.add_entity(Entity::new_splitter_with_priority(
Beltspeed::from_items_per_second(
input_connections
.iter()
.chain(output_connections.iter())
.map(|&(_, c)| c.amount)
.max_by(|x, y| x.partial_cmp(y).unwrap())
.unwrap_or(1.0),
),
Position::new(2, 1),
Direction::Up,
None,
Some(true),
));
let macro_block = MacroBlock {
size: Position::new(2, 1),
input: vec![
Interface {
offset: Position::new(0, 0),
dir: Direction::Up,
},
Interface {
offset: Position::new(1, 0),
dir: Direction::Up,
},
],
output: vec![
Interface {
offset: Position::new(0, 0),
dir: Direction::Up,
},
Interface {
offset: Position::new(1, 0),
dir: Direction::Up,
},
],
};
let mut output_index = 0;
let mut input_index = 1;
let mut amount = input_connections[0].1.amount;
let mut intermediate_connections_input = HashMap::from([(
input_connections[0].0,
IntermediateConnectionEntry {
block: Some(block_index),
interface: 0,
},
)]);
let mut intermediate_connections_output = HashMap::new();
loop {
while input_index < input_connections.len()
&& amount + input_connections[input_index].1.amount
< output_connections[output_index].1.amount
{
if input_index > 1 || output_index > 0 {
connections.push(Connection {
startblock: Some(blocks.len() - 1),
startpoint: 1,
endblock: Some(blocks.len()),
endpoint: 0,
lanes: 1,
beltspeed: Beltspeed::Turbo,
});
}
intermediate_connections_input.insert(
input_connections[input_index].0,
IntermediateConnectionEntry {
block: Some(blocks.len()),
interface: 1,
},
);
blueprints.push(blueprint.clone());
blocks.push(macro_block.clone());
amount += input_connections[input_index].1.amount;
input_index += 1;
}
if input_index > 1 || output_index > 0 {
connections.push(Connection {
startblock: Some(blocks.len() - 1),
startpoint: 1,
endblock: Some(blocks.len()),
endpoint: 0,
lanes: 1,
beltspeed: Beltspeed::Turbo,
});
}
if amount >= output_connections[output_index].1.amount {
intermediate_connections_output.insert(
output_connections[output_index].0,
IntermediateConnectionEntry {
block: Some(blocks.len()),
interface: 0,
},
);
blueprints.push(blueprint.clone());
blocks.push(macro_block.clone());
} else {
intermediate_connections_output.insert(
output_connections[output_index].0,
IntermediateConnectionEntry {
block: Some(blocks.len()),
interface: 0,
},
);
intermediate_connections_input.insert(
input_connections[input_index].0,
IntermediateConnectionEntry {
block: Some(blocks.len()),
interface: 1,
},
);
blueprints.push(blueprint.clone());
blocks.push(macro_block.clone());
amount += input_connections[input_index].1.amount;
input_index += 1;
}
amount -= output_connections[output_index].1.amount;
output_index += 1;
if output_index >= output_connections.len() - 1 {
break;
}
}
if output_connections.len() > 1 {
intermediate_connections_output.insert(
output_connections.last().unwrap().0,
IntermediateConnectionEntry {
block: Some(blocks.len() - 1),
interface: 1,
},
);
}
// dbg!(
// &input_connections,
// &output_connections,
// &intermediate_connections_input,
// &intermediate_connections_output,
// amount,
// );
intermediate_connections.push(IntermediateConnection {
input: intermediate_connections_input,
output: intermediate_connections_output,
});
}
} }
} }
// dbg!(&intermediate_connections); // dbg!(&intermediate_connections);

View file

@ -1,7 +1,8 @@
use factorio_blueprint::abstraction::{Blueprint, Entity, RailType, UndergroundType};
use factorio_core::{beltoptions::Beltspeed, prelude::*};
use crate::{balancer::binary_balancer, station::basic_station}; use crate::{balancer::binary_balancer, station::basic_station};
use factorio_blueprint::abstraction::{
Blueprint, ElectricPoleType, Entity, RailType, UndergroundType,
};
use factorio_core::{beltoptions::Beltspeed, prelude::*};
pub struct StationSpec { pub struct StationSpec {
pub locomotives: usize, pub locomotives: usize,
@ -52,6 +53,12 @@ pub fn multistation(
let mut blueprint = Blueprint::new(); let mut blueprint = Blueprint::new();
// connection power pole
blueprint.add_entity(Entity::new_electric_pole(
ElectricPoleType::Big,
Position::new(32, 0),
));
// stacker // stacker
let stacker_length = (longest_train * 5).div_ceil(2); let stacker_length = (longest_train * 5).div_ceil(2);
blueprint.add_entity(Entity::new_rail( blueprint.add_entity(Entity::new_rail(

View file

@ -140,7 +140,11 @@ pub struct Entity {
pub enum EntityType { pub enum EntityType {
Belt(Beltspeed), Belt(Beltspeed),
UndergroundBelt(Beltspeed, UndergroundType), UndergroundBelt(Beltspeed, UndergroundType),
Splitter(Beltspeed), Splitter {
beltspeed: Beltspeed,
input_priority_left: Option<bool>,
output_priority_left: Option<bool>,
},
ElectricPole(ElectricPoleType), ElectricPole(ElectricPoleType),
Inserter { Inserter {
inserter_type: InserterType, inserter_type: InserterType,
@ -203,9 +207,34 @@ impl Entity {
} }
pub fn new_splitter(beltspeed: Beltspeed, position: Position, direction: Direction) -> Self { pub fn new_splitter(beltspeed: Beltspeed, position: Position, direction: Direction) -> Self {
Self::new(EntityType::Splitter(beltspeed), position, direction) Self::new(
EntityType::Splitter {
beltspeed,
input_priority_left: None,
output_priority_left: None,
},
position,
direction,
)
} }
pub fn new_splitter_with_priority(
beltspeed: Beltspeed,
position: Position,
direction: Direction,
input_priority_left: Option<bool>,
output_priority_left: Option<bool>,
) -> Self {
Self::new(
EntityType::Splitter {
beltspeed,
input_priority_left,
output_priority_left,
},
position,
direction,
)
}
pub fn new_inserter( pub fn new_inserter(
inserter_type: InserterType, inserter_type: InserterType,
override_stack_size: Option<u8>, override_stack_size: Option<u8>,
@ -288,7 +317,11 @@ impl Entity {
EntityType::UndergroundBelt(beltspeed, _underground_type) => { EntityType::UndergroundBelt(beltspeed, _underground_type) => {
beltspeed.string_underground() beltspeed.string_underground()
} }
EntityType::Splitter(beltspeed) => beltspeed.string_splitter(), EntityType::Splitter {
beltspeed,
input_priority_left: _,
output_priority_left: _,
} => beltspeed.string_splitter(),
EntityType::Unknown { EntityType::Unknown {
name, name,
size: _, size: _,
@ -340,9 +373,38 @@ impl Entity {
} }
} }
pub fn get_maybe_input_priority(&self) -> Option<String> {
match self.entity {
EntityType::Splitter {
beltspeed: _,
input_priority_left,
output_priority_left: _,
} => match input_priority_left {
Some(true) => Some("left".to_string()),
Some(false) => Some("right".to_string()),
None => None,
},
_ => None,
}
}
pub fn get_maybe_output_priority(&self) -> Option<String> {
match self.entity {
EntityType::Splitter {
beltspeed: _,
input_priority_left: _,
output_priority_left,
} => match output_priority_left {
Some(true) => Some("left".to_string()),
Some(false) => Some("right".to_string()),
None => None,
},
_ => None,
}
}
pub fn size(&self) -> Position { pub fn size(&self) -> Position {
match &self.entity { match &self.entity {
EntityType::Splitter(_) => Position::new(4, 2), EntityType::Splitter { .. } => Position::new(4, 2),
EntityType::Unknown { EntityType::Unknown {
name: _, name: _,
size, size,
@ -416,7 +478,7 @@ impl Entity {
); );
} }
}, },
EntityType::Splitter(_beltspeed) => (), EntityType::Splitter { .. } => (),
EntityType::ElectricPole(electric_pole_type) => match electric_pole_type { EntityType::ElectricPole(electric_pole_type) => match electric_pole_type {
ElectricPoleType::Small => v.add_symbol( ElectricPoleType::Small => v.add_symbol(
(self.position - Position::new(1, 1)) / 2 + offset, (self.position - Position::new(1, 1)) / 2 + offset,
@ -473,6 +535,7 @@ pub struct EntityKey(usize);
static ENTITY_COUNTER: AtomicUsize = AtomicUsize::new(0); static ENTITY_COUNTER: AtomicUsize = AtomicUsize::new(0);
#[derive(Clone)]
pub struct Blueprint { pub struct Blueprint {
entities: Vec<(EntityKey, Entity)>, entities: Vec<(EntityKey, Entity)>,
keys: HashMap<EntityKey, usize>, keys: HashMap<EntityKey, usize>,
@ -566,6 +629,8 @@ impl Blueprint {
.maybe_underground_type(e.get_maybe_underground_type_string()) .maybe_underground_type(e.get_maybe_underground_type_string())
.maybe_override_stack_size(e.get_maybe_override_stack_size()) .maybe_override_stack_size(e.get_maybe_override_stack_size())
.maybe_recipe(e.get_maybe_recipe()) .maybe_recipe(e.get_maybe_recipe())
.maybe_input_priority(e.get_maybe_input_priority())
.maybe_output_priority(e.get_maybe_output_priority())
.build() .build()
}) })
.collect(); .collect();