use bevy::reflect::Reflect;
use crate::prelude::*;
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Default, Debug, Clone, Reflect)]
pub struct Portals {
north: Vec<FieldCell>,
east: Vec<FieldCell>,
south: Vec<FieldCell>,
west: Vec<FieldCell>,
}
impl Portals {
#[cfg(not(tarpaulin_include))]
pub fn get(&self, ordinal: &Ordinal) -> &Vec<FieldCell> {
match ordinal {
Ordinal::North => &self.north,
Ordinal::East => &self.east,
Ordinal::South => &self.south,
Ordinal::West => &self.west,
_ => panic!("Ordinal {:?} is invalid when looking up portals", ordinal),
}
}
#[cfg(not(tarpaulin_include))]
pub fn get_mut(&mut self, ordinal: &Ordinal) -> &mut Vec<FieldCell> {
match ordinal {
Ordinal::North => &mut self.north,
Ordinal::East => &mut self.east,
Ordinal::South => &mut self.south,
Ordinal::West => &mut self.west,
_ => panic!("Ordinal {:?} is invalid when looking up portals", ordinal),
}
}
fn clear(&mut self, ordinal: Ordinal) {
match ordinal {
Ordinal::North => self.north.clear(),
Ordinal::East => self.east.clear(),
Ordinal::South => self.south.clear(),
Ordinal::West => self.west.clear(),
_ => panic!(
"Ordinal {:?} is invalid when clearing a portal side",
ordinal
),
}
}
fn clear_all(&mut self) {
let ords = [Ordinal::North, Ordinal::South, Ordinal::West, Ordinal::East];
for ord in ords {
self.clear(ord);
}
}
pub fn recalculate_portals(
&mut self,
sector_cost_fields: &SectorCostFields,
sector_id: &SectorID,
map_dimensions: &MapDimensions,
) {
self.clear_all();
let valid_ordinals_for_this_sector: Vec<(Ordinal, SectorID)> =
map_dimensions.get_ordinal_and_ids_of_neighbouring_sectors(sector_id);
let cost_field = sector_cost_fields
.get_scaled()
.get(sector_id)
.expect("Invalid sector id");
for (ord, adjoining_sector_id) in valid_ordinals_for_this_sector.iter() {
match ord {
Ordinal::North => {
let portal_nodes = self.get_mut(ord);
let column_range = 0..FIELD_RESOLUTION;
let fixed_row = 0;
let adjoining_cost_field = sector_cost_fields
.get_scaled()
.get(adjoining_sector_id)
.unwrap();
let mut neighbouring_pathable = Vec::new();
for i in column_range {
let field_cost =
cost_field.get_field_cell_value(FieldCell::new(i, fixed_row));
let adjacent_field_cost = adjoining_cost_field
.get_field_cell_value(FieldCell::new(i, FIELD_RESOLUTION - 1));
if field_cost != 255 && adjacent_field_cost != 255 {
neighbouring_pathable.push((i, fixed_row));
} else {
if !neighbouring_pathable.is_empty() {
let mut column_index_sum = 0;
for (m, _) in neighbouring_pathable.iter() {
column_index_sum += m;
}
let portal_midpoint_column =
column_index_sum / neighbouring_pathable.len();
portal_nodes
.push(FieldCell::new(portal_midpoint_column, fixed_row));
neighbouring_pathable.clear();
}
}
}
if !neighbouring_pathable.is_empty() {
let mut column_index_sum = 0;
for (i, _) in neighbouring_pathable.iter() {
column_index_sum += i;
}
let portal_midpoint_column = column_index_sum / neighbouring_pathable.len();
portal_nodes.push(FieldCell::new(portal_midpoint_column, fixed_row));
neighbouring_pathable.clear();
}
}
Ordinal::East => {
let portal_nodes = self.get_mut(ord);
let fixed_column = FIELD_RESOLUTION - 1;
let row_range = 0..FIELD_RESOLUTION;
let adjoining_cost_field = sector_cost_fields
.get_scaled()
.get(adjoining_sector_id)
.unwrap();
let mut neighbouring_pathable = Vec::new();
for j in row_range {
let field_cost =
cost_field.get_field_cell_value(FieldCell::new(fixed_column, j));
let adjacent_field_cost =
adjoining_cost_field.get_field_cell_value(FieldCell::new(0, j));
if field_cost != 255 && adjacent_field_cost != 255 {
neighbouring_pathable.push((fixed_column, j));
} else {
if !neighbouring_pathable.is_empty() {
let mut row_index_sum = 0;
for (_, n) in neighbouring_pathable.iter() {
row_index_sum += n;
}
let portal_midpoint_row =
row_index_sum / neighbouring_pathable.len();
portal_nodes
.push(FieldCell::new(fixed_column, portal_midpoint_row));
neighbouring_pathable.clear();
}
}
}
if !neighbouring_pathable.is_empty() {
let mut row_index_sum = 0;
for (_, n) in neighbouring_pathable.iter() {
row_index_sum += n;
}
let portal_midpoint_row = row_index_sum / neighbouring_pathable.len();
portal_nodes.push(FieldCell::new(fixed_column, portal_midpoint_row));
neighbouring_pathable.clear();
}
}
Ordinal::South => {
let portal_nodes = self.get_mut(ord);
let column_range = 0..FIELD_RESOLUTION;
let fixed_row = FIELD_RESOLUTION - 1;
let adjoining_cost_field = sector_cost_fields
.get_scaled()
.get(adjoining_sector_id)
.unwrap();
let mut neighbouring_pathable = Vec::new();
for i in column_range {
let field_cost =
cost_field.get_field_cell_value(FieldCell::new(i, fixed_row));
let adjacent_field_cost =
adjoining_cost_field.get_field_cell_value(FieldCell::new(i, 0));
if field_cost != 255 && adjacent_field_cost != 255 {
neighbouring_pathable.push((i, fixed_row));
} else {
if !neighbouring_pathable.is_empty() {
let mut column_index_sum = 0;
for (m, _) in neighbouring_pathable.iter() {
column_index_sum += m;
}
let portal_midpoint_column =
column_index_sum / neighbouring_pathable.len();
portal_nodes
.push(FieldCell::new(portal_midpoint_column, fixed_row));
neighbouring_pathable.clear();
}
}
}
if !neighbouring_pathable.is_empty() {
let mut column_index_sum = 0;
for (i, _) in neighbouring_pathable.iter() {
column_index_sum += i;
}
let portal_midpoint_column = column_index_sum / neighbouring_pathable.len();
portal_nodes.push(FieldCell::new(portal_midpoint_column, fixed_row));
neighbouring_pathable.clear();
}
}
Ordinal::West => {
let portal_nodes = self.get_mut(ord);
let fixed_column = 0;
let row_range = 0..FIELD_RESOLUTION;
let adjoining_cost_field = sector_cost_fields
.get_scaled()
.get(adjoining_sector_id)
.unwrap();
let mut neighbouring_pathable = Vec::new();
for j in row_range {
let field_cost =
cost_field.get_field_cell_value(FieldCell::new(fixed_column, j));
let adjacent_field_cost = adjoining_cost_field
.get_field_cell_value(FieldCell::new(FIELD_RESOLUTION - 1, j));
if field_cost != 255 && adjacent_field_cost != 255 {
neighbouring_pathable.push((fixed_column, j));
} else {
if !neighbouring_pathable.is_empty() {
let mut row_index_sum = 0;
for (_, n) in neighbouring_pathable.iter() {
row_index_sum += n;
}
let portal_midpoint_row =
row_index_sum / neighbouring_pathable.len();
portal_nodes
.push(FieldCell::new(fixed_column, portal_midpoint_row));
neighbouring_pathable.clear();
}
}
}
if !neighbouring_pathable.is_empty() {
let mut row_index_sum = 0;
for (_, n) in neighbouring_pathable.iter() {
row_index_sum += n;
}
let portal_midpoint_row = row_index_sum / neighbouring_pathable.len();
portal_nodes.push(FieldCell::new(fixed_column, portal_midpoint_row));
neighbouring_pathable.clear();
}
}
_ => panic!(
"Portal ordinals can only be North, East, South or West. Asked for {:?}",
ord
),
};
}
}
pub fn expand_portal_into_goals(
&self,
sector_cost_fields: &SectorCostFields,
sector_id: &SectorID,
portal_id: &FieldCell,
neighbour_sector_id: &SectorID,
map_dimensions: &MapDimensions,
) -> Vec<FieldCell> {
let mut boundary_ordinals = portal_id.get_boundary_ordinal_from_field_cell();
if boundary_ordinals.len() > 1 {
let valid_ordinals_for_this_sector: Vec<(Ordinal, SectorID)> =
map_dimensions.get_ordinal_and_ids_of_neighbouring_sectors(sector_id);
'outer: for (ordinal, id) in valid_ordinals_for_this_sector.iter() {
if id == neighbour_sector_id {
boundary_ordinals.retain(|o| o == ordinal);
break 'outer;
}
}
if boundary_ordinals.len() > 1 {
panic!("Sector {:?} does not have a neighbour at {:?} while inspecting portal {:?}. This suggests that a portal exists on a sector boundary where it shouldn't, i.e this sector is along an edge of the world and the portal is on a boundary leading to nowhere", sector_id, neighbour_sector_id, portal_id);
}
}
let boundary_ordinal = boundary_ordinals.first().unwrap();
let mut goals: Vec<FieldCell> = Vec::new();
goals.push(*portal_id);
let this_cost_field = sector_cost_fields.get_scaled().get(sector_id).unwrap();
let adjoining_cost_field = sector_cost_fields
.get_scaled()
.get(neighbour_sector_id)
.unwrap();
match boundary_ordinal {
Ordinal::North => {
let mut step = 1;
'left: while portal_id.get_column().checked_sub(step).is_some() {
let left = FieldCell::new(portal_id.get_column() - step, portal_id.get_row());
let left_cost = this_cost_field
.get_field_cell_value(FieldCell::new(left.get_column(), left.get_row()));
let neighbour_cost = adjoining_cost_field.get_field_cell_value(FieldCell::new(
left.get_column(),
FIELD_RESOLUTION - 1,
));
if left_cost != 255 && neighbour_cost != 255 {
goals.push(left);
step += 1;
} else {
break 'left;
}
}
let mut step = 1;
'right: while portal_id.get_column() + step < FIELD_RESOLUTION {
let right = FieldCell::new(portal_id.get_column() + step, portal_id.get_row());
let right_cost = this_cost_field.get_field_cell_value(right);
let neighbour_cost = adjoining_cost_field.get_field_cell_value(FieldCell::new(
right.get_column(),
FIELD_RESOLUTION - 1,
));
if right_cost != 255 && neighbour_cost != 255 {
goals.push(right);
step += 1;
} else {
break 'right;
}
}
}
Ordinal::East => {
let mut step = 1;
'up: while portal_id.get_row().checked_sub(step).is_some() {
let up = FieldCell::new(portal_id.get_column(), portal_id.get_row() - step);
let up_cost = this_cost_field.get_field_cell_value(up);
let neighbour_cost =
adjoining_cost_field.get_field_cell_value(FieldCell::new(0, up.get_row()));
if up_cost != 255 && neighbour_cost != 255 {
goals.push(up);
step += 1;
} else {
break 'up;
}
}
let mut step = 1;
'down: while portal_id.get_row() + step < FIELD_RESOLUTION {
let down = FieldCell::new(portal_id.get_column(), portal_id.get_row() + step);
let right_cost = this_cost_field.get_field_cell_value(down);
let neighbour_cost = adjoining_cost_field
.get_field_cell_value(FieldCell::new(0, down.get_row()));
if right_cost != 255 && neighbour_cost != 255 {
goals.push(down);
step += 1;
} else {
break 'down;
}
}
}
Ordinal::South => {
let mut step = 1;
'left: while portal_id.get_column().checked_sub(step).is_some() {
let left = FieldCell::new(portal_id.get_column() - step, portal_id.get_row());
let left_cost = this_cost_field.get_field_cell_value(left);
let neighbour_cost = adjoining_cost_field
.get_field_cell_value(FieldCell::new(left.get_column(), 0));
if left_cost != 255 && neighbour_cost != 255 {
goals.push(left);
step += 1;
} else {
break 'left;
}
}
let mut step = 1;
'right: while portal_id.get_column() + step < FIELD_RESOLUTION {
let right = FieldCell::new(portal_id.get_column() + step, portal_id.get_row());
let right_cost = this_cost_field.get_field_cell_value(right);
let neighbour_cost = adjoining_cost_field
.get_field_cell_value(FieldCell::new(right.get_column(), 0));
if right_cost != 255 && neighbour_cost != 255 {
goals.push(right);
step += 1;
} else {
break 'right;
}
}
}
Ordinal::West => {
let mut step = 1;
'up: while portal_id.get_row().checked_sub(step).is_some() {
let up = FieldCell::new(portal_id.get_column(), portal_id.get_row() - step);
let up_cost = this_cost_field.get_field_cell_value(up);
let neighbour_cost = adjoining_cost_field
.get_field_cell_value(FieldCell::new(FIELD_RESOLUTION - 1, up.get_row()));
if up_cost != 255 && neighbour_cost != 255 {
goals.push(up);
step += 1;
} else {
break 'up;
}
}
let mut step = 1;
'down: while portal_id.get_row() + step < FIELD_RESOLUTION {
let down = FieldCell::new(portal_id.get_column(), portal_id.get_row() + step);
let right_cost = this_cost_field.get_field_cell_value(down);
let neighbour_cost = adjoining_cost_field
.get_field_cell_value(FieldCell::new(FIELD_RESOLUTION - 1, down.get_row()));
if right_cost != 255 && neighbour_cost != 255 {
goals.push(down);
step += 1;
} else {
break 'down;
}
}
}
_ => panic!(
"Invalid Ordinal {:?} for boundary walking",
boundary_ordinal
),
}
goals
}
}
#[cfg(test)]
mod tests {
use crate::flowfields::sectors::sector_portals::SectorPortals;
use super::*;
#[test]
fn portals_top_left_sector() {
let map_dimensions = MapDimensions::new(30, 30, 10, 0.5);
let mut sector_cost_fields = SectorCostFields::new(&map_dimensions);
let sector_id = SectorID::new(0, 0);
sector_cost_fields.set_field_cell_value(
sector_id,
255,
FieldCell::new(9, 5),
&map_dimensions,
);
sector_cost_fields.set_field_cell_value(
sector_id,
255,
FieldCell::new(0, 9),
&map_dimensions,
);
let mut portals = Portals::default();
portals.recalculate_portals(§or_cost_fields, §or_id, &map_dimensions);
let northern_side_portal_count = 0;
let eastern_side_portal_count = 2;
let southern_side_portal_count = 1;
let western_side_portal_count = 0;
assert_eq!(northern_side_portal_count, portals.north.len());
assert_eq!(eastern_side_portal_count, portals.east.len());
assert_eq!(southern_side_portal_count, portals.south.len());
assert_eq!(western_side_portal_count, portals.west.len());
}
#[test]
fn portals_top_middle_sector() {
let map_dimensions = MapDimensions::new(30, 30, 10, 0.5);
let mut sector_cost_fields = SectorCostFields::new(&map_dimensions);
let sector_id = SectorID::new(1, 0);
sector_cost_fields.set_field_cell_value(
sector_id,
255,
FieldCell::new(9, 5),
&map_dimensions,
);
sector_cost_fields.set_field_cell_value(
sector_id,
255,
FieldCell::new(0, 9),
&map_dimensions,
);
let mut portals = Portals::default();
portals.recalculate_portals(§or_cost_fields, §or_id, &map_dimensions);
let northern_side_portal_count = 0;
let eastern_side_portal_count = 2;
let southern_side_portal_count = 1;
let western_side_portal_count = 1;
assert_eq!(northern_side_portal_count, portals.north.len());
assert_eq!(eastern_side_portal_count, portals.east.len());
assert_eq!(southern_side_portal_count, portals.south.len());
assert_eq!(western_side_portal_count, portals.west.len());
}
#[test]
fn portals_centre_sector() {
let map_dimensions = MapDimensions::new(30, 30, 10, 0.5);
let mut sector_cost_fields = SectorCostFields::new(&map_dimensions);
let sector_id = SectorID::new(1, 1);
sector_cost_fields.set_field_cell_value(
sector_id,
255,
FieldCell::new(9, 5),
&map_dimensions,
);
sector_cost_fields.set_field_cell_value(
sector_id,
255,
FieldCell::new(0, 9),
&map_dimensions,
);
let mut portals = Portals::default();
portals.recalculate_portals(§or_cost_fields, §or_id, &map_dimensions);
let northern_side_portal_count = 1;
let eastern_side_portal_count = 2;
let southern_side_portal_count = 1;
let western_side_portal_count = 1;
assert_eq!(northern_side_portal_count, portals.north.len());
assert_eq!(eastern_side_portal_count, portals.east.len());
assert_eq!(southern_side_portal_count, portals.south.len());
assert_eq!(western_side_portal_count, portals.west.len());
}
#[test]
fn portals_bottom_middle_sector() {
let map_dimensions = MapDimensions::new(30, 30, 10, 0.5);
let mut sector_cost_fields = SectorCostFields::new(&map_dimensions);
let sector_id = SectorID::new(1, 2);
sector_cost_fields.set_field_cell_value(
sector_id,
255,
FieldCell::new(4, 0),
&map_dimensions,
);
sector_cost_fields.set_field_cell_value(
sector_id,
255,
FieldCell::new(6, 0),
&map_dimensions,
);
sector_cost_fields.set_field_cell_value(
sector_id,
255,
FieldCell::new(9, 5),
&map_dimensions,
);
sector_cost_fields.set_field_cell_value(
sector_id,
255,
FieldCell::new(0, 9),
&map_dimensions,
);
let mut portals = Portals::default();
portals.recalculate_portals(§or_cost_fields, §or_id, &map_dimensions);
let northern_side_portal_count = 3;
let eastern_side_portal_count = 2;
let southern_side_portal_count = 0;
let western_side_portal_count = 1;
assert_eq!(northern_side_portal_count, portals.north.len());
assert_eq!(eastern_side_portal_count, portals.east.len());
assert_eq!(southern_side_portal_count, portals.south.len());
assert_eq!(western_side_portal_count, portals.west.len());
}
#[test]
fn verify_rebuilding() {
let map_dimensions = MapDimensions::new(30, 30, 10, 0.5);
let mut sector_cost_fields = SectorCostFields::new(&map_dimensions);
let mut sector_portals = SectorPortals::new(
map_dimensions.get_length(),
map_dimensions.get_depth(),
map_dimensions.get_sector_resolution(),
);
for (id, portals) in sector_portals.get_mut().iter_mut() {
portals.recalculate_portals(§or_cost_fields, id, &map_dimensions)
}
let pre_first = sector_portals
.get_mut()
.get_mut(&SectorID::new(0, 0))
.unwrap()
.clone();
let pre_second = sector_portals
.get_mut()
.get_mut(&SectorID::new(0, 1))
.unwrap()
.clone();
println!("Pre update portals {:?}", pre_first);
println!("Pre update portals {:?}", pre_second);
let mutated_sector_id = SectorID::new(0, 0);
sector_cost_fields.set_field_cell_value(
mutated_sector_id,
255,
FieldCell::new(4, 9),
&map_dimensions,
);
sector_portals.update_portals(mutated_sector_id, §or_cost_fields, &map_dimensions);
let post_first = sector_portals
.get_mut()
.get_mut(&mutated_sector_id)
.unwrap()
.clone();
let post_second = sector_portals
.get_mut()
.get_mut(&SectorID::new(0, 1))
.unwrap()
.clone();
println!("Updated portals {:?}", post_first);
println!("Updated portals {:?}", post_second);
let actual_first = vec![FieldCell::new(1, 9), FieldCell::new(7, 9)];
let actual_second = vec![FieldCell::new(1, 0), FieldCell::new(7, 0)];
assert_eq!(actual_first, *post_first.get(&Ordinal::South));
assert_eq!(actual_second, *post_second.get(&Ordinal::North));
}
#[test]
fn expand_portal_goals_north() {
let map_dimensions = MapDimensions::new(30, 30, 10, 0.5);
let sector_cost_fields = SectorCostFields::new(&map_dimensions);
let mut sector_portals = SectorPortals::new(
map_dimensions.get_length(),
map_dimensions.get_depth(),
map_dimensions.get_sector_resolution(),
);
for (id, portals) in sector_portals.get_mut().iter_mut() {
portals.recalculate_portals(§or_cost_fields, id, &map_dimensions)
}
let sector_id = SectorID::new(1, 1);
let portal_id = FieldCell::new(4, 0);
let neighbour_sector_id = SectorID::new(1, 0);
let goals = sector_portals
.get()
.get(§or_id)
.unwrap()
.expand_portal_into_goals(
§or_cost_fields,
§or_id,
&portal_id,
&neighbour_sector_id,
&map_dimensions,
);
let actual = vec![
FieldCell::new(4, 0),
FieldCell::new(3, 0),
FieldCell::new(2, 0),
FieldCell::new(1, 0),
FieldCell::new(0, 0),
FieldCell::new(5, 0),
FieldCell::new(6, 0),
FieldCell::new(7, 0),
FieldCell::new(8, 0),
FieldCell::new(9, 0),
];
assert_eq!(actual, goals);
}
#[test]
fn expand_portal_goals_east() {
let map_dimensions = MapDimensions::new(30, 30, 10, 0.5);
let sector_cost_fields = SectorCostFields::new(&map_dimensions);
let mut sector_portals = SectorPortals::new(
map_dimensions.get_length(),
map_dimensions.get_depth(),
map_dimensions.get_sector_resolution(),
);
for (id, portals) in sector_portals.get_mut().iter_mut() {
portals.recalculate_portals(§or_cost_fields, id, &map_dimensions)
}
let sector_id = SectorID::new(1, 1);
let portal_id = FieldCell::new(9, 4);
let neighbour_sector_id = SectorID::new(2, 1);
let goals = sector_portals
.get()
.get(§or_id)
.unwrap()
.expand_portal_into_goals(
§or_cost_fields,
§or_id,
&portal_id,
&neighbour_sector_id,
&map_dimensions,
);
let actual = vec![
FieldCell::new(9, 4),
FieldCell::new(9, 3),
FieldCell::new(9, 2),
FieldCell::new(9, 1),
FieldCell::new(9, 0),
FieldCell::new(9, 5),
FieldCell::new(9, 6),
FieldCell::new(9, 7),
FieldCell::new(9, 8),
FieldCell::new(9, 9),
];
assert_eq!(actual, goals);
}
#[test]
fn expand_portal_goals_south() {
let map_dimensions = MapDimensions::new(30, 30, 10, 0.5);
let sector_cost_fields = SectorCostFields::new(&map_dimensions);
let mut sector_portals = SectorPortals::new(
map_dimensions.get_length(),
map_dimensions.get_depth(),
map_dimensions.get_sector_resolution(),
);
for (id, portals) in sector_portals.get_mut().iter_mut() {
portals.recalculate_portals(§or_cost_fields, id, &map_dimensions)
}
let sector_id = SectorID::new(1, 1);
let portal_id = FieldCell::new(4, 9);
let neighbour_sector_id = SectorID::new(1, 2);
let goals = sector_portals
.get()
.get(§or_id)
.unwrap()
.expand_portal_into_goals(
§or_cost_fields,
§or_id,
&portal_id,
&neighbour_sector_id,
&map_dimensions,
);
let actual = vec![
FieldCell::new(4, 9),
FieldCell::new(3, 9),
FieldCell::new(2, 9),
FieldCell::new(1, 9),
FieldCell::new(0, 9),
FieldCell::new(5, 9),
FieldCell::new(6, 9),
FieldCell::new(7, 9),
FieldCell::new(8, 9),
FieldCell::new(9, 9),
];
assert_eq!(actual, goals);
}
#[test]
fn expand_portal_goals_west() {
let map_dimensions = MapDimensions::new(30, 30, 10, 0.5);
let sector_cost_fields = SectorCostFields::new(&map_dimensions);
let mut sector_portals = SectorPortals::new(
map_dimensions.get_length(),
map_dimensions.get_depth(),
map_dimensions.get_sector_resolution(),
);
for (id, portals) in sector_portals.get_mut().iter_mut() {
portals.recalculate_portals(§or_cost_fields, id, &map_dimensions)
}
let sector_id = SectorID::new(1, 1);
let portal_id = FieldCell::new(0, 4);
let neighbour_sector_id = SectorID::new(0, 1);
let goals = sector_portals
.get()
.get(§or_id)
.unwrap()
.expand_portal_into_goals(
§or_cost_fields,
§or_id,
&portal_id,
&neighbour_sector_id,
&map_dimensions,
);
let actual = vec![
FieldCell::new(0, 4),
FieldCell::new(0, 3),
FieldCell::new(0, 2),
FieldCell::new(0, 1),
FieldCell::new(0, 0),
FieldCell::new(0, 5),
FieldCell::new(0, 6),
FieldCell::new(0, 7),
FieldCell::new(0, 8),
FieldCell::new(0, 9),
];
assert_eq!(actual, goals);
}
#[test]
fn expand_portal_goals_short_local() {
let map_dimensions = MapDimensions::new(30, 30, 10, 0.5);
let sector_id = SectorID::new(1, 1);
let neighbour_sector_id = SectorID::new(1, 0);
let mut sector_cost_fields = SectorCostFields::new(&map_dimensions);
sector_cost_fields.set_field_cell_value(
sector_id,
255,
FieldCell::new(3, 0),
&map_dimensions,
);
let mut sector_portals = SectorPortals::new(
map_dimensions.get_length(),
map_dimensions.get_depth(),
map_dimensions.get_sector_resolution(),
);
for (id, portals) in sector_portals.get_mut().iter_mut() {
portals.recalculate_portals(§or_cost_fields, id, &map_dimensions)
}
let portal_id = FieldCell::new(1, 0);
let goals = sector_portals
.get()
.get(§or_id)
.unwrap()
.expand_portal_into_goals(
§or_cost_fields,
§or_id,
&portal_id,
&neighbour_sector_id,
&map_dimensions,
);
let actual = vec![
FieldCell::new(1, 0),
FieldCell::new(0, 0),
FieldCell::new(2, 0),
];
assert_eq!(actual, goals);
}
#[test]
fn expand_portal_goals_short_adjacent() {
let map_dimensions = MapDimensions::new(30, 30, 10, 0.5);
let sector_id = SectorID::new(1, 1);
let neighbour_sector_id = SectorID::new(1, 0);
let mut sector_cost_fields = SectorCostFields::new(&map_dimensions);
sector_cost_fields.set_field_cell_value(
neighbour_sector_id,
255,
FieldCell::new(3, 9),
&map_dimensions,
);
let mut sector_portals = SectorPortals::new(
map_dimensions.get_length(),
map_dimensions.get_depth(),
map_dimensions.get_sector_resolution(),
);
for (id, portals) in sector_portals.get_mut().iter_mut() {
portals.recalculate_portals(§or_cost_fields, id, &map_dimensions)
}
let portal_id = FieldCell::new(1, 0);
let goals = sector_portals
.get()
.get(§or_id)
.unwrap()
.expand_portal_into_goals(
§or_cost_fields,
§or_id,
&portal_id,
&neighbour_sector_id,
&map_dimensions,
);
let actual = vec![
FieldCell::new(1, 0),
FieldCell::new(0, 0),
FieldCell::new(2, 0),
];
assert_eq!(actual, goals);
}
}