mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Make sure location hint calculation is only done once.
Location hint calculation is expensive and should not be done
in a hot loop.
This is a fixup for 1572a5a759
.
This commit is contained in:
parent
e71eee0cd2
commit
1d0329cfa7
@ -107,20 +107,22 @@ impl ProximitySpec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ProximityRequirements {
|
struct ProximityRequirementsBuilder {
|
||||||
all_of: Vec<ProximitySpec>,
|
all_of: Vec<ProximitySpec>,
|
||||||
any_of: Vec<ProximitySpec>,
|
any_of: Vec<ProximitySpec>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProximityRequirements {
|
impl ProximityRequirementsBuilder {
|
||||||
pub fn satisfied_by(&self, site: Vec2<i32>) -> bool {
|
pub fn finalize(self, world_dims: &Aabr<i32>) -> ProximityRequirements {
|
||||||
let all_of_compliance = self.all_of.iter().all(|spec| spec.satisfied_by(site));
|
let location_hint = self.location_hint(world_dims);
|
||||||
let any_of_compliance =
|
ProximityRequirements {
|
||||||
self.any_of.is_empty() || self.any_of.iter().any(|spec| spec.satisfied_by(site));
|
all_of: self.all_of,
|
||||||
all_of_compliance && any_of_compliance
|
any_of: self.any_of,
|
||||||
|
location_hint,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn location_hint(&self, world_dims: &Aabr<i32>) -> Aabr<i32> {
|
fn location_hint(&self, world_dims: &Aabr<i32>) -> Aabr<i32> {
|
||||||
let bounding_box_of_point = |point: Vec2<i32>, max_distance: i32| Aabr {
|
let bounding_box_of_point = |point: Vec2<i32>, max_distance: i32| Aabr {
|
||||||
min: Vec2 {
|
min: Vec2 {
|
||||||
x: point.x - max_distance,
|
x: point.x - max_distance,
|
||||||
@ -162,7 +164,7 @@ impl ProximityRequirements {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
ProximityRequirements {
|
Self {
|
||||||
all_of: Vec::new(),
|
all_of: Vec::new(),
|
||||||
any_of: Vec::new(),
|
any_of: Vec::new(),
|
||||||
}
|
}
|
||||||
@ -189,6 +191,25 @@ impl ProximityRequirements {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ProximityRequirements {
|
||||||
|
all_of: Vec<ProximitySpec>,
|
||||||
|
any_of: Vec<ProximitySpec>,
|
||||||
|
location_hint: Aabr<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProximityRequirements {
|
||||||
|
pub fn satisfied_by(&self, site: Vec2<i32>) -> bool {
|
||||||
|
if self.location_hint.contains_point(site) {
|
||||||
|
let all_of_compliance = self.all_of.iter().all(|spec| spec.satisfied_by(site));
|
||||||
|
let any_of_compliance =
|
||||||
|
self.any_of.is_empty() || self.any_of.iter().any(|spec| spec.satisfied_by(site));
|
||||||
|
all_of_compliance && any_of_compliance
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, R: Rng> GenCtx<'a, R> {
|
impl<'a, R: Rng> GenCtx<'a, R> {
|
||||||
pub fn reseed(&mut self) -> GenCtx<'_, impl Rng> {
|
pub fn reseed(&mut self) -> GenCtx<'_, impl Rng> {
|
||||||
let mut entropy = self.rng.gen::<[u8; 32]>();
|
let mut entropy = self.rng.gen::<[u8; 32]>();
|
||||||
@ -235,15 +256,17 @@ impl Civs {
|
|||||||
info!(?initial_civ_count, "all civilisations created");
|
info!(?initial_civ_count, "all civilisations created");
|
||||||
|
|
||||||
prof_span!(guard, "find locations and establish sites");
|
prof_span!(guard, "find locations and establish sites");
|
||||||
|
let world_dims = ctx.sim.get_aabr();
|
||||||
for _ in 0..initial_civ_count * 3 {
|
for _ in 0..initial_civ_count * 3 {
|
||||||
attempt(5, || {
|
attempt(5, || {
|
||||||
let (loc, kind) = match ctx.rng.gen_range(0..64) {
|
let (loc, kind) = match ctx.rng.gen_range(0..64) {
|
||||||
0..=5 => (
|
0..=5 => (
|
||||||
find_site_loc(
|
find_site_loc(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
&ProximityRequirements::new()
|
&ProximityRequirementsBuilder::new()
|
||||||
.avoid_all_of(this.castle_enemies(), 40)
|
.avoid_all_of(this.castle_enemies(), 40)
|
||||||
.close_to_one_of(this.towns(), 20),
|
.close_to_one_of(this.towns(), 20)
|
||||||
|
.finalize(&world_dims),
|
||||||
SiteKind::Castle,
|
SiteKind::Castle,
|
||||||
)?,
|
)?,
|
||||||
SiteKind::Castle,
|
SiteKind::Castle,
|
||||||
@ -253,8 +276,9 @@ impl Civs {
|
|||||||
(
|
(
|
||||||
find_site_loc(
|
find_site_loc(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
&ProximityRequirements::new()
|
&ProximityRequirementsBuilder::new()
|
||||||
.avoid_all_of(this.tree_enemies(), 40),
|
.avoid_all_of(this.tree_enemies(), 40)
|
||||||
|
.finalize(&world_dims),
|
||||||
SiteKind::GiantTree,
|
SiteKind::GiantTree,
|
||||||
)?,
|
)?,
|
||||||
SiteKind::GiantTree,
|
SiteKind::GiantTree,
|
||||||
@ -263,8 +287,9 @@ impl Civs {
|
|||||||
(
|
(
|
||||||
find_site_loc(
|
find_site_loc(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
&ProximityRequirements::new()
|
&ProximityRequirementsBuilder::new()
|
||||||
.avoid_all_of(this.tree_enemies(), 40),
|
.avoid_all_of(this.tree_enemies(), 40)
|
||||||
|
.finalize(&world_dims),
|
||||||
SiteKind::Tree,
|
SiteKind::Tree,
|
||||||
)?,
|
)?,
|
||||||
SiteKind::Tree,
|
SiteKind::Tree,
|
||||||
@ -274,7 +299,9 @@ impl Civs {
|
|||||||
32..=37 => (
|
32..=37 => (
|
||||||
find_site_loc(
|
find_site_loc(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
&ProximityRequirements::new().avoid_all_of(this.gnarling_enemies(), 40),
|
&ProximityRequirementsBuilder::new()
|
||||||
|
.avoid_all_of(this.gnarling_enemies(), 40)
|
||||||
|
.finalize(&world_dims),
|
||||||
SiteKind::Gnarling,
|
SiteKind::Gnarling,
|
||||||
)?,
|
)?,
|
||||||
SiteKind::Gnarling,
|
SiteKind::Gnarling,
|
||||||
@ -283,8 +310,9 @@ impl Civs {
|
|||||||
38..=43 => (
|
38..=43 => (
|
||||||
find_site_loc(
|
find_site_loc(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
&ProximityRequirements::new()
|
&ProximityRequirementsBuilder::new()
|
||||||
.avoid_all_of(this.chapel_site_enemies(), 40),
|
.avoid_all_of(this.chapel_site_enemies(), 40)
|
||||||
|
.finalize(&world_dims),
|
||||||
SiteKind::ChapelSite,
|
SiteKind::ChapelSite,
|
||||||
)?,
|
)?,
|
||||||
SiteKind::ChapelSite,
|
SiteKind::ChapelSite,
|
||||||
@ -292,7 +320,9 @@ impl Civs {
|
|||||||
44..=49 => (
|
44..=49 => (
|
||||||
find_site_loc(
|
find_site_loc(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
&ProximityRequirements::new().avoid_all_of(this.gnarling_enemies(), 40),
|
&ProximityRequirementsBuilder::new()
|
||||||
|
.avoid_all_of(this.gnarling_enemies(), 40)
|
||||||
|
.finalize(&world_dims),
|
||||||
SiteKind::Adlet,
|
SiteKind::Adlet,
|
||||||
)?,
|
)?,
|
||||||
SiteKind::Adlet,
|
SiteKind::Adlet,
|
||||||
@ -300,7 +330,9 @@ impl Civs {
|
|||||||
_ => (
|
_ => (
|
||||||
find_site_loc(
|
find_site_loc(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
&ProximityRequirements::new().avoid_all_of(this.dungeon_enemies(), 40),
|
&ProximityRequirementsBuilder::new()
|
||||||
|
.avoid_all_of(this.dungeon_enemies(), 40)
|
||||||
|
.finalize(&world_dims),
|
||||||
SiteKind::Dungeon,
|
SiteKind::Dungeon,
|
||||||
)?,
|
)?,
|
||||||
SiteKind::Dungeon,
|
SiteKind::Dungeon,
|
||||||
@ -763,9 +795,11 @@ impl Civs {
|
|||||||
13..=18 => SiteKind::SavannahPit,
|
13..=18 => SiteKind::SavannahPit,
|
||||||
_ => SiteKind::Refactor,
|
_ => SiteKind::Refactor,
|
||||||
};
|
};
|
||||||
|
let world_dims = ctx.sim.get_aabr();
|
||||||
let site = attempt(100, || {
|
let site = attempt(100, || {
|
||||||
let avoid_town_enemies =
|
let avoid_town_enemies = ProximityRequirementsBuilder::new()
|
||||||
ProximityRequirements::new().avoid_all_of(self.town_enemies(), 60);
|
.avoid_all_of(self.town_enemies(), 60)
|
||||||
|
.finalize(&world_dims);
|
||||||
let loc = find_site_loc(ctx, &avoid_town_enemies, kind)?;
|
let loc = find_site_loc(ctx, &avoid_town_enemies, kind)?;
|
||||||
Some(self.establish_site(ctx, loc, |place| Site {
|
Some(self.establish_site(ctx, loc, |place| Site {
|
||||||
kind,
|
kind,
|
||||||
@ -1502,15 +1536,8 @@ fn find_site_loc(
|
|||||||
prof_span!("find_site_loc");
|
prof_span!("find_site_loc");
|
||||||
const MAX_ATTEMPTS: usize = 10000;
|
const MAX_ATTEMPTS: usize = 10000;
|
||||||
let mut loc = None;
|
let mut loc = None;
|
||||||
|
let location_hint = proximity_reqs.location_hint;
|
||||||
for _ in 0..MAX_ATTEMPTS {
|
for _ in 0..MAX_ATTEMPTS {
|
||||||
let world_dims = Aabr {
|
|
||||||
min: Vec2 { x: 0, y: 0 },
|
|
||||||
max: Vec2 {
|
|
||||||
x: ctx.sim.get_size().x as i32,
|
|
||||||
y: ctx.sim.get_size().y as i32,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let location_hint = proximity_reqs.location_hint(&world_dims);
|
|
||||||
let test_loc = loc.unwrap_or_else(|| {
|
let test_loc = loc.unwrap_or_else(|| {
|
||||||
Vec2::new(
|
Vec2::new(
|
||||||
ctx.rng.gen_range(location_hint.min.x..location_hint.max.x),
|
ctx.rng.gen_range(location_hint.min.x..location_hint.max.x),
|
||||||
@ -1868,22 +1895,51 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_proximity_requirements() {
|
fn empty_proximity_requirements() {
|
||||||
let reqs = ProximityRequirements::new();
|
let world_dims = Aabr {
|
||||||
|
min: Vec2 { x: 0, y: 0 },
|
||||||
|
max: Vec2 {
|
||||||
|
x: 200_i32,
|
||||||
|
y: 200_i32,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let reqs = ProximityRequirementsBuilder::new().finalize(&world_dims);
|
||||||
assert!(reqs.satisfied_by(Vec2 { x: 0, y: 0 }));
|
assert!(reqs.satisfied_by(Vec2 { x: 0, y: 0 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn avoid_proximity_requirements() {
|
fn avoid_proximity_requirements() {
|
||||||
let reqs =
|
let world_dims = Aabr {
|
||||||
ProximityRequirements::new().avoid_all_of(vec![Vec2 { x: 0, y: 0 }].into_iter(), 10);
|
min: Vec2 {
|
||||||
|
x: -200_i32,
|
||||||
|
y: -200_i32,
|
||||||
|
},
|
||||||
|
max: Vec2 {
|
||||||
|
x: 200_i32,
|
||||||
|
y: 200_i32,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let reqs = ProximityRequirementsBuilder::new()
|
||||||
|
.avoid_all_of(vec![Vec2 { x: 0, y: 0 }].into_iter(), 10)
|
||||||
|
.finalize(&world_dims);
|
||||||
assert!(reqs.satisfied_by(Vec2 { x: 8, y: -8 }));
|
assert!(reqs.satisfied_by(Vec2 { x: 8, y: -8 }));
|
||||||
assert!(!reqs.satisfied_by(Vec2 { x: -1, y: 1 }));
|
assert!(!reqs.satisfied_by(Vec2 { x: -1, y: 1 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn near_proximity_requirements() {
|
fn near_proximity_requirements() {
|
||||||
let reqs =
|
let world_dims = Aabr {
|
||||||
ProximityRequirements::new().close_to_one_of(vec![Vec2 { x: 0, y: 0 }].into_iter(), 10);
|
min: Vec2 {
|
||||||
|
x: -200_i32,
|
||||||
|
y: -200_i32,
|
||||||
|
},
|
||||||
|
max: Vec2 {
|
||||||
|
x: 200_i32,
|
||||||
|
y: 200_i32,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let reqs = ProximityRequirementsBuilder::new()
|
||||||
|
.close_to_one_of(vec![Vec2 { x: 0, y: 0 }].into_iter(), 10)
|
||||||
|
.finalize(&world_dims);
|
||||||
assert!(reqs.satisfied_by(Vec2 { x: 1, y: -1 }));
|
assert!(reqs.satisfied_by(Vec2 { x: 1, y: -1 }));
|
||||||
assert!(!reqs.satisfied_by(Vec2 { x: -8, y: 8 }));
|
assert!(!reqs.satisfied_by(Vec2 { x: -8, y: 8 }));
|
||||||
}
|
}
|
||||||
@ -1891,16 +1947,24 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn complex_proximity_requirements() {
|
fn complex_proximity_requirements() {
|
||||||
let a_site = Vec2 { x: 572, y: 724 };
|
let a_site = Vec2 { x: 572, y: 724 };
|
||||||
let reqs = ProximityRequirements::new()
|
let world_dims = Aabr {
|
||||||
|
min: Vec2 { x: 0, y: 0 },
|
||||||
|
max: Vec2 {
|
||||||
|
x: 1000_i32,
|
||||||
|
y: 1000_i32,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let reqs = ProximityRequirementsBuilder::new()
|
||||||
.close_to_one_of(vec![a_site].into_iter(), 60)
|
.close_to_one_of(vec![a_site].into_iter(), 60)
|
||||||
.avoid_all_of(vec![a_site].into_iter(), 40);
|
.avoid_all_of(vec![a_site].into_iter(), 40)
|
||||||
|
.finalize(&world_dims);
|
||||||
assert!(reqs.satisfied_by(Vec2 { x: 572, y: 774 }));
|
assert!(reqs.satisfied_by(Vec2 { x: 572, y: 774 }));
|
||||||
assert!(!reqs.satisfied_by(a_site));
|
assert!(!reqs.satisfied_by(a_site));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn location_hint() {
|
fn location_hint() {
|
||||||
let reqs = ProximityRequirements::new().close_to_one_of(
|
let reqs = ProximityRequirementsBuilder::new().close_to_one_of(
|
||||||
vec![Vec2 { x: 1, y: 0 }, Vec2 { x: 13, y: 12 }].into_iter(),
|
vec![Vec2 { x: 1, y: 0 }, Vec2 { x: 13, y: 12 }].into_iter(),
|
||||||
10,
|
10,
|
||||||
);
|
);
|
||||||
|
@ -1581,6 +1581,17 @@ impl WorldSim {
|
|||||||
|
|
||||||
pub fn get_size(&self) -> Vec2<u32> { self.map_size_lg().chunks().map(u32::from) }
|
pub fn get_size(&self) -> Vec2<u32> { self.map_size_lg().chunks().map(u32::from) }
|
||||||
|
|
||||||
|
pub fn get_aabr(&self) -> Aabr<i32> {
|
||||||
|
let size = self.get_size();
|
||||||
|
Aabr {
|
||||||
|
min: Vec2 { x: 0, y: 0 },
|
||||||
|
max: Vec2 {
|
||||||
|
x: size.x as i32,
|
||||||
|
y: size.y as i32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn generate_oob_chunk(&self) -> TerrainChunk {
|
pub fn generate_oob_chunk(&self) -> TerrainChunk {
|
||||||
TerrainChunk::water(CONFIG.sea_level as i32)
|
TerrainChunk::water(CONFIG.sea_level as i32)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user