fn next_step(&mut self, src: Point, dsts: &[Point]) -> Option<Point> {
    if dsts.is_empty() {
      return None;
    }
    self.clear();
    // loop until all vacancies are visited or one of |dsts| is reached
    let mut visiting = Vec::<(Point, Point)>::with_capacity(256);
    let mut to_visit = Vec::<(Point, Point)>::with_capacity(256);
    // order flipped since Vec::{push, pop} is FILO
    to_visit.push((Point(src.0, src.1 + 1), src));
    to_visit.push((Point(src.0 + 1, src.1), src));
    to_visit.push((Point(src.0 - 1, src.1), src));
    to_visit.push((Point(src.0, src.1 - 1), src));
    let mut cur_dist = 0;
    let mut final_dst: Option<Point> = None;
    let mut almost_reached = false;

    while !to_visit.is_empty() {
      mem::swap(&mut visiting, &mut to_visit);
      to_visit.clear();
      cur_dist += 1;
      while let Some((pt, from)) = visiting.pop() {
        let cell = self.cell(pt); // proceed only if cell is vacant
        if let Some(Cell::Vacant { previous, dist }) = cell {
          // if path shorter or if same distance tie break with previous point
          if dist > cur_dist || ((dist == cur_dist) && (previous > from)) {
            self.set(
              pt,
              Cell::Vacant {
                previous: from,
                dist: cur_dist,
              },
            );
            if dsts.iter().any(|&p| p == pt) {
              final_dst = match final_dst {
                None => {
                  // Reached first target; stop futher outer loop iterations as
                  // |cur_dist| only increases; we won’t find a closer target.
                  // Process inner loop to completion since another target with
                  // same dist but preceding |pt| in reading order may be found.
                  almost_reached = true;
                  to_visit.clear();
                  Some(pt)
                }
                Some(old_dst) => match pt < old_dst {
                  true => Some(pt),
                  false => final_dst,
                },
              };
            }
            if !almost_reached {
              to_visit.push((Point(pt.0, pt.1 + 1), pt));
              to_visit.push((Point(pt.0 + 1, pt.1), pt));
              to_visit.push((Point(pt.0 - 1, pt.1), pt));
              to_visit.push((Point(pt.0, pt.1 - 1), pt));
            }
          }
        }
      }
    }

    // if found a path, backtrack and choose the optimal next step
    match final_dst {
      Some(mut pt) => {
        loop {
          match self.layout[self.point_to_idx(pt)] {
            Cell::Vacant { previous, .. } => match self.is_vacant(previous) {
              true => pt = previous,
              false => break,
            },
            _ => unreachable!(),
          }
        }
        Some(pt)
      }
      None => None,
    }
  }
/** Deduce possible next step for unit at `src` */
Deduce possible next step for unit at `src`
Deduce possible next step for unit at ` src `
fn next_step(&mut self, src: Point, dsts: &[Point]) -> Option<Point> {
    if dsts.is_empty() {
      return None;
    }
    self.clear();
    // loop until all vacancies are visited or one of |dsts| is reached
    let mut visiting = Vec::<(Point, Point)>::with_capacity(256);
    let mut to_visit = Vec::<(Point, Point)>::with_capacity(256);
    // order flipped since Vec::{push, pop} is FILO
    to_visit.push((Point(src.0, src.1 + 1), src));
    to_visit.push((Point(src.0 + 1, src.1), src));
    to_visit.push((Point(src.0 - 1, src.1), src));
    to_visit.push((Point(src.0, src.1 - 1), src));
    let mut cur_dist = 0;
    let mut final_dst: Option<Point> = None;
    let mut almost_reached = false;
    while !to_visit.is_empty() {
      mem::swap(&mut visiting, &mut to_visit);
      to_visit.clear();
      cur_dist += 1;
      while let Some((pt, from)) = visiting.pop() {
        let cell = self.cell(pt); // proceed only if cell is vacant
        if let Some(Cell::Vacant { previous, dist }) = cell {
          // if path shorter or if same distance tie break with previous point
          if dist > cur_dist || ((dist == cur_dist) && (previous > from)) {
            self.set(
              pt,
              Cell::Vacant {
                previous: from,
                dist: cur_dist,
              },
            );
            if dsts.iter().any(|&p| p == pt) {
              final_dst = match final_dst {
                None => {
                  // Reached first target; stop futher outer loop iterations as
                  // |cur_dist| only increases; we won’t find a closer target.
                  // Process inner loop to completion since another target with
                  // same dist but preceding |pt| in reading order may be found.
                  almost_reached = true;
                  to_visit.clear();
                  Some(pt)
                }
                Some(old_dst) => match pt < old_dst {
                  true => Some(pt),
                  false => final_dst,
                },
              };
            }
            if !almost_reached {
              to_visit.push((Point(pt.0, pt.1 + 1), pt));
              to_visit.push((Point(pt.0 + 1, pt.1), pt));
              to_visit.push((Point(pt.0 - 1, pt.1), pt));
              to_visit.push((Point(pt.0, pt.1 - 1), pt));
            }
          }
        }
      }
    }
    // if found a path, backtrack and choose the optimal next step
    match final_dst {
      Some(mut pt) => {
        loop {
          match self.layout[self.point_to_idx(pt)] {
            Cell::Vacant { previous, .. } => match self.is_vacant(previous) {
              true => pt = previous,
              false => break,
            },
            _ => unreachable!(),
          }
        }
        Some(pt)
      }
      None => None,
    }
  }
fn next_step ( & mut self , src : Point , dsts : & [ Point ] ) -> Option < Point > { if dsts . is_empty ( ) { return None ; } self . clear ( ) ; // loop until all vacancies are visited or one of |dsts| is reached let mut visiting = Vec :: < ( Point , Point ) > :: with_capacity ( 256 ) ; let mut to_visit = Vec :: < ( Point , Point ) > :: with_capacity ( 256 ) ; // order flipped since Vec::{push, pop} is FILO to_visit . push ( ( Point ( src . 0 , src . 1 + 1 ) , src ) ) ; to_visit . push ( ( Point ( src . 0 + 1 , src . 1 ) , src ) ) ; to_visit . push ( ( Point ( src . 0 - 1 , src . 1 ) , src ) ) ; to_visit . push ( ( Point ( src . 0 , src . 1 - 1 ) , src ) ) ; let mut cur_dist = 0 ; let mut final_dst : Option < Point > = None ; let mut almost_reached = false ; while ! to_visit . is_empty ( ) { mem :: swap ( & mut visiting , & mut to_visit ) ; to_visit . clear ( ) ; cur_dist += 1 ; while let Some ( ( pt , from ) ) = visiting . pop ( ) { let cell = self . cell ( pt ) ; // proceed only if cell is vacant if let Some ( Cell :: Vacant { previous , dist } ) = cell { // if path shorter or if same distance tie break with previous point if dist > cur_dist || ( ( dist == cur_dist ) && ( previous > from ) ) { self . set ( pt , Cell :: Vacant { previous : from , dist : cur_dist , } , ) ; if dsts . iter ( ) . any ( | & p | p == pt ) { final_dst = match final_dst { None => { // Reached first target; stop futher outer loop iterations as // |cur_dist| only increases; we won’t find a closer target. // Process inner loop to completion since another target with // same dist but preceding |pt| in reading order may be found. almost_reached = true ; to_visit . clear ( ) ; Some ( pt ) } Some ( old_dst ) => match pt < old_dst { true => Some ( pt ) , false => final_dst , } , } ; } if ! almost_reached { to_visit . push ( ( Point ( pt . 0 , pt . 1 + 1 ) , pt ) ) ; to_visit . push ( ( Point ( pt . 0 + 1 , pt . 1 ) , pt ) ) ; to_visit . push ( ( Point ( pt . 0 - 1 , pt . 1 ) , pt ) ) ; to_visit . push ( ( Point ( pt . 0 , pt . 1 - 1 ) , pt ) ) ; } } } } } // if found a path, backtrack and choose the optimal next step match final_dst { Some ( mut pt ) => { loop { match self . layout [ self . point_to_idx ( pt ) ] { Cell :: Vacant { previous , .. } => match self . is_vacant ( previous ) { true => pt = previous , false => break , } , _ => unreachable ! ( ) , } } Some ( pt ) } None => None , } }
Deduce possible next step for unit at `src`
Deduce possible next step for unit at ` src `
&mut self
src
Point
dsts
&[Point]