Add candidate selection.

This commit is contained in:
hal8174 2024-01-21 15:29:20 +01:00
parent 207a0436d8
commit 8f6809c17f
3 changed files with 148 additions and 50 deletions

View file

@ -20,6 +20,48 @@ pub struct ConflictAvoidance {
belts: Vec<Vec<PathField>>,
}
#[derive(Debug, PartialEq, Eq)]
struct Candidate {
min: Position,
max: Position,
}
impl Candidate {
fn new(min: Position, max: Position) -> Self {
Self { min, max }
}
fn area(&self) -> PositionType {
(self.max.x - self.min.x) * (self.max.y - self.min.y)
}
fn extend_range(&mut self, conflict_map: &Map<usize>) {
for x in self.min.x..=self.max.x {
if self.min.y > 0 && *conflict_map.get(x as usize, self.min.y as usize) > 1 {
self.min.y -= 1;
return self.extend_range(conflict_map);
}
if (self.max.y as usize) < conflict_map.height - 1
&& *conflict_map.get(x as usize, self.max.y as usize) > 1
{
self.max.y += 1;
return self.extend_range(conflict_map);
}
}
for y in self.min.y..=self.max.y {
if self.min.x > 0 && *conflict_map.get(self.min.x as usize, y as usize) > 1 {
self.min.x -= 1;
return self.extend_range(conflict_map);
}
if (self.max.x as usize) < conflict_map.width - 1
&& *conflict_map.get(self.max.x as usize, y as usize) > 1
{
self.max.x += 1;
return self.extend_range(conflict_map);
}
}
}
}
impl ConflictAvoidance {
pub fn new(problem: Problem) -> Self {
let mut map: Map<Field> = Map::new(problem.map.width, problem.map.height);
@ -50,33 +92,6 @@ impl ConflictAvoidance {
Self { map, belts }
}
fn extend_range(
conflict_map: &Map<usize>,
xrange: &mut RangeInclusive<usize>,
yrange: &mut RangeInclusive<usize>,
) {
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<usize> = Map::new(self.map.width, self.map.height);
@ -114,37 +129,32 @@ impl ConflictAvoidance {
println!();
}
let mut c = None;
let mut candidates = Vec::new();
for y in 0..self.map.height {
for x in 0..self.map.width {
if *conflicts.get(x, y) > 1 {
c = Some((x, y));
break;
let mut candidate = Candidate::new(
Position::new(x as PositionType, y as PositionType),
Position::new(x as PositionType, y as PositionType),
);
candidate.extend_range(&conflicts);
if !candidates.iter().any(|c| c == &candidate) {
candidates.push(candidate);
}
}
}
}
let (cx, cy) = match c {
Some(c) => c,
None => {
return false;
}
};
let xoffset = 1;
let yoffset = 1;
let mut xrange = cx..=cx;
let mut yrange = cy..=cy;
if candidates.is_empty() {
return false;
}
loop {
xrange = xrange.start().saturating_sub(xoffset)
..=usize::min(xrange.end() + xoffset, self.map.width - 1);
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);
candidates.sort_by_key(|c| -c.area());
let c = candidates.pop().unwrap();
let mut xrange = c.min.x as usize..=c.max.x as usize;
let mut yrange = c.min.y as usize..=c.max.y as usize;
println!("x: {:?}, y: {:?}", xrange, yrange);
@ -261,6 +271,57 @@ impl ConflictAvoidance {
}
return true;
} else {
let mut candidate = Candidate::new(
Position::new(
xrange.start().saturating_sub(1) as PositionType,
*yrange.start() as PositionType,
),
Position::new(*xrange.end() as PositionType, *yrange.end() as PositionType),
);
candidate.extend_range(&conflicts);
if candidate != c && !candidates.iter().any(|c| c == &candidate) {
candidates.push(candidate);
}
let mut candidate = Candidate::new(
Position::new(
*xrange.start() as PositionType,
yrange.start().saturating_sub(1) as PositionType,
),
Position::new(*xrange.end() as PositionType, *yrange.end() as PositionType),
);
candidate.extend_range(&conflicts);
if candidate != c && !candidates.iter().any(|c| c == &candidate) {
candidates.push(candidate);
}
let mut candidate = Candidate::new(
Position::new(
*xrange.start() as PositionType,
*yrange.start() as PositionType,
),
Position::new(
usize::min(xrange.end() + 1, self.map.width - 1) as PositionType,
*yrange.end() as PositionType,
),
);
candidate.extend_range(&conflicts);
if candidate != c && !candidates.iter().any(|c| c == &candidate) {
candidates.push(candidate);
}
let mut candidate = Candidate::new(
Position::new(
*xrange.start() as PositionType,
*yrange.start() as PositionType,
),
Position::new(
*xrange.end() as PositionType,
usize::min(yrange.end() + 1, self.map.height - 1) as PositionType,
),
);
candidate.extend_range(&conflicts);
if candidate != c && !candidates.iter().any(|c| c == &candidate) {
candidates.push(candidate);
}
}
}
}