diff --git a/examples/solve_belt.rs b/examples/solve_belt.rs index b7ab3f7..2bf49a3 100644 --- a/examples/solve_belt.rs +++ b/examples/solve_belt.rs @@ -1,3 +1,5 @@ +use std::io; + use clap::{Parser, ValueEnum}; use factorio_blueprint::belt_finding::{conflict_avoidance::ConflictAvoidance, problems, Problem}; @@ -5,6 +7,7 @@ use factorio_blueprint::belt_finding::{conflict_avoidance::ConflictAvoidance, pr enum Mode { Solve, ConflictAvoidance, + ConflictStep, } #[derive(ValueEnum, Clone)] @@ -51,5 +54,17 @@ fn main() { println!("{}", c) } } + Mode::ConflictStep => { + println!("{}", p); + p.find_path(); + println!("{}", p); + let mut c = ConflictAvoidance::new(p); + println!("{}", c); + while c.remove_conflict() { + println!("{}", c); + let mut s = String::new(); + let _ = io::stdin().read_line(&mut s); + } + } } } diff --git a/src/belt_finding/conflict_avoidance.rs b/src/belt_finding/conflict_avoidance.rs index f45564e..ce82942 100644 --- a/src/belt_finding/conflict_avoidance.rs +++ b/src/belt_finding/conflict_avoidance.rs @@ -1,4 +1,4 @@ -use std::fmt::Display; +use std::{fmt::Display, ops::RangeInclusive}; use colored::Colorize; @@ -49,6 +49,33 @@ impl ConflictAvoidance { Self { map, belts } } + fn extend_range( + conflict_map: &Map, + xrange: &mut RangeInclusive, + yrange: &mut RangeInclusive, + ) { + for x in xrange.clone() { + if *yrange.start() > 0 && *conflict_map.get(x, *yrange.start()) > 1 { + *yrange = *yrange.start() - 1..=*yrange.end(); + return Self::extend_range(conflict_map, xrange, yrange); + } + if *yrange.end() < conflict_map.height - 1 && *conflict_map.get(x, *yrange.end()) > 1 { + *yrange = *yrange.start()..=*yrange.end() + 1; + return Self::extend_range(conflict_map, xrange, yrange); + } + } + for y in yrange.clone() { + if *xrange.start() > 0 && *conflict_map.get(*xrange.start(), y) > 1 { + *xrange = *xrange.start() - 1..=*xrange.end(); + return Self::extend_range(conflict_map, xrange, yrange); + } + if *xrange.end() < conflict_map.width - 1 && *conflict_map.get(*xrange.end(), y) > 1 { + *xrange = *xrange.start()..=*xrange.end() + 1; + return Self::extend_range(conflict_map, xrange, yrange); + } + } + } + pub fn remove_conflict(&mut self) -> bool { let mut conflicts: Map = Map::new(self.map.width, self.map.height); @@ -110,21 +137,21 @@ impl ConflictAvoidance { } }; - let mut xoffset = 0; - let mut yoffset = 0; + let xoffset = 1; + let yoffset = 1; + + let mut xrange = cx..=cx; + let mut yrange = cy..=cy; loop { - xoffset += 1; - yoffset += 1; - - let xrange = cx..=cx; - let yrange = cy..=cy; - - let xrange = xrange.start().saturating_sub(xoffset) + xrange = xrange.start().saturating_sub(xoffset) ..=usize::min(xrange.end() + xoffset, self.map.width - 1); - let yrange = yrange.start().saturating_sub(yoffset) + yrange = yrange.start().saturating_sub(yoffset) ..=usize::min(yrange.end() + yoffset, self.map.height - 1); + println!("x: {:?}, y: {:?}", xrange, yrange); + Self::extend_range(&conflicts, &mut xrange, &mut yrange); + println!("x: {:?}, y: {:?}", xrange, yrange); let xsize = xrange.end() - xrange.start() + 1; @@ -163,11 +190,13 @@ impl ConflictAvoidance { .position(|p| xrange.contains(&p.x) && yrange.contains(&p.y)) .map(|i| usize::min(path.len() - 1, path.len() - i)); - if let Some((start, end)) = s.zip(e) { + if let Some((start, mut end)) = s.zip(e) { // dbg!(start, end); - mapping.push((i, start, end)); + if matches!(path[end - 1], PathField::Underground { .. }) { + end -= 1; + } - // dbg!(path[start], path[end]); + mapping.push((i, start, end)); let (start_pos, start_dir) = path[start] .end_pos(&Dimension { @@ -179,6 +208,7 @@ impl ConflictAvoidance { let end_dir = path[end].dir(); // dbg!(start_pos, end_pos); + // dbg!(i, path[start], path[end]); b.add_path( ( diff --git a/src/misc/map.rs b/src/misc/map.rs index a7ae828..7506781 100644 --- a/src/misc/map.rs +++ b/src/misc/map.rs @@ -27,15 +27,35 @@ where } pub fn get(&self, x: usize, y: usize) -> &T { - assert!(x < self.width); - assert!(y < self.height); + assert!( + x < self.width, + "assertion failed: x < self.width; x: {}, self.width: {}", + x, + self.width + ); + assert!( + y < self.height, + "assertion failed: y < self.height; y: {}, self.height: {}", + y, + self.height + ); let i = self.index(x, y); self.data.get(i).unwrap() } pub fn get_mut(&mut self, x: usize, y: usize) -> &mut T { - assert!(x < self.width); - assert!(y < self.height); + assert!( + x < self.width, + "assertion failed: x < self.width; x: {}, self.width: {}", + x, + self.width + ); + assert!( + y < self.height, + "assertion failed: y < self.height; y: {}, self.height: {}", + y, + self.height + ); let i = self.index(x, y); self.data.get_mut(i).unwrap() }