Better town layout

This commit is contained in:
Joshua Barretto 2023-04-04 11:06:51 +01:00
parent 06820dbf16
commit 85c572f6e2
8 changed files with 38 additions and 65 deletions

View File

@ -87,7 +87,7 @@ impl<S: Clone + Eq + Hash + fmt::Debug, H: BuildHasher> fmt::Debug for Astar<S,
}
impl<S: Clone + Eq + Hash, H: BuildHasher + Clone> Astar<S, H> {
pub fn new(max_iters: usize, start: S, heuristic: impl FnOnce(&S) -> f32, hasher: H) -> Self {
pub fn new(max_iters: usize, start: S, hasher: H) -> Self {
Self {
max_iters,
iter: 0,
@ -104,7 +104,7 @@ impl<S: Clone + Eq + Hash, H: BuildHasher + Clone> Astar<S, H> {
},
final_scores: {
let mut h = HashMap::with_capacity_and_hasher(1, hasher.clone());
h.extend(core::iter::once((start.clone(), heuristic(&start))));
h.extend(core::iter::once((start.clone(), 0.0)));
h
},
visited: {
@ -120,7 +120,7 @@ impl<S: Clone + Eq + Hash, H: BuildHasher + Clone> Astar<S, H> {
pub fn poll<I>(
&mut self,
iters: usize,
mut heuristic: impl FnMut(&S) -> f32,
mut heuristic: impl FnMut(&S, &S) -> f32,
mut neighbors: impl FnMut(&S) -> I,
mut transition: impl FnMut(&S, &S) -> f32,
mut satisfied: impl FnMut(&S) -> bool,
@ -143,7 +143,7 @@ impl<S: Clone + Eq + Hash, H: BuildHasher + Clone> Astar<S, H> {
if cost < *neighbor_cheapest {
self.came_from.insert(neighbor.clone(), node.clone());
self.cheapest_scores.insert(neighbor.clone(), cost);
let h = heuristic(&neighbor);
let h = heuristic(&neighbor, &node);
let neighbor_cost = cost + h;
self.final_scores.insert(neighbor.clone(), neighbor_cost);

View File

@ -534,7 +534,7 @@ where
_ => return (None, false),
};
let heuristic = |pos: &Vec3<i32>| (pos.distance_squared(end) as f32).sqrt();
let heuristic = |pos: &Vec3<i32>, _: &Vec3<i32>| (pos.distance_squared(end) as f32).sqrt();
let neighbors = |pos: &Vec3<i32>| {
let pos = *pos;
const DIRS: [Vec3<i32>; 17] = [
@ -639,7 +639,7 @@ where
let satisfied = |pos: &Vec3<i32>| pos == &end;
let mut new_astar = match astar.take() {
None => Astar::new(25_000, start, heuristic, DefaultHashBuilder::default()),
None => Astar::new(25_000, start, DefaultHashBuilder::default()),
Some(astar) => astar,
};

View File

@ -929,13 +929,13 @@ pub fn handle_manipulate_loadout(
let iters =
(3.0 * (sprite_pos_f32 - data.pos.0).map(|x| x.abs()).sum()) as usize;
// Heuristic compares manhattan distance of start and end pos
let heuristic =
move |pos: &Vec3<i32>| (sprite_pos - pos).map(|x| x.abs()).sum() as f32;
let heuristic = move |pos: &Vec3<i32>, _: &Vec3<i32>| {
(sprite_pos - pos).map(|x| x.abs()).sum() as f32
};
let mut astar = Astar::new(
iters,
data.pos.0.map(|x| x.floor() as i32),
heuristic,
BuildHasherDefault::<FxHasher64>::default(),
);

View File

@ -43,13 +43,8 @@ const CARDINALS: &[Vec2<i32>] = &[
];
fn path_in_site(start: Vec2<i32>, end: Vec2<i32>, site: &site2::Site) -> PathResult<Vec2<i32>> {
let heuristic = |tile: &Vec2<i32>| tile.as_::<f32>().distance(end.as_());
let mut astar = Astar::new(
1000,
start,
heuristic,
BuildHasherDefault::<FxHasher64>::default(),
);
let heuristic = |tile: &Vec2<i32>, _: &Vec2<i32>| tile.as_::<f32>().distance(end.as_());
let mut astar = Astar::new(1000, start, BuildHasherDefault::<FxHasher64>::default());
let transition = |a: &Vec2<i32>, b: &Vec2<i32>| {
let distance = a.as_::<f32>().distance(b.as_());
@ -128,14 +123,10 @@ fn path_between_sites(
let get_site = |site: &Id<civ::Site>| world.civs().sites.get(*site);
let end_pos = get_site(&end).center.as_::<f32>();
let heuristic = |site: &Id<civ::Site>| get_site(site).center.as_().distance(end_pos);
let heuristic =
|site: &Id<civ::Site>, _: &Id<civ::Site>| get_site(site).center.as_().distance(end_pos);
let mut astar = Astar::new(
250,
start,
heuristic,
BuildHasherDefault::<FxHasher64>::default(),
);
let mut astar = Astar::new(250, start, BuildHasherDefault::<FxHasher64>::default());
let neighbors = |site: &Id<civ::Site>| world.civs().neighbors(*site);
@ -734,14 +725,10 @@ fn chunk_path(
to: Vec2<i32>,
chunk_height: impl Fn(Vec2<i32>) -> Option<i32>,
) -> Box<dyn Action> {
let heuristics = |(p, _): &(Vec2<i32>, i32)| p.distance_squared(to) as f32;
let heuristics =
|(p, _): &(Vec2<i32>, i32), _: &(Vec2<i32>, i32)| p.distance_squared(to) as f32;
let start = (from, chunk_height(from).unwrap());
let mut astar = Astar::new(
1000,
start,
heuristics,
BuildHasherDefault::<FxHasher64>::default(),
);
let mut astar = Astar::new(1000, start, BuildHasherDefault::<FxHasher64>::default());
let path = astar.poll(
1000,

View File

@ -659,7 +659,7 @@ impl Civs {
/// Find the cheapest route between two places
fn route_between(&self, a: Id<Site>, b: Id<Site>) -> Option<(Path<Id<Site>>, f32)> {
let heuristic = move |p: &Id<Site>| {
let heuristic = move |p: &Id<Site>, _: &Id<Site>| {
(self
.sites
.get(*p)
@ -676,12 +676,7 @@ impl Civs {
// (1) we don't care about DDOS attacks (ruling out SipHash);
// (2) we care about determinism across computers (ruling out AAHash);
// (3) we have 8-byte keys (for which FxHash is fastest).
let mut astar = Astar::new(
100,
a,
heuristic,
BuildHasherDefault::<FxHasher64>::default(),
);
let mut astar = Astar::new(100, a, BuildHasherDefault::<FxHasher64>::default());
astar
.poll(100, heuristic, neighbors, transition, satisfied)
.into_path()
@ -1306,7 +1301,7 @@ fn find_path(
) -> Option<(Path<Vec2<i32>>, f32)> {
const MAX_PATH_ITERS: usize = 100_000;
let sim = &ctx.sim;
let heuristic = move |l: &Vec2<i32>| (l.distance_squared(b) as f32).sqrt();
let heuristic = move |l: &Vec2<i32>, _: &Vec2<i32>| (l.distance_squared(b) as f32).sqrt();
let get_bridge = &get_bridge;
let neighbors = |l: &Vec2<i32>| {
let l = *l;
@ -1327,7 +1322,6 @@ fn find_path(
let mut astar = Astar::new(
MAX_PATH_ITERS,
a,
heuristic,
BuildHasherDefault::<FxHasher64>::default(),
);
astar

View File

@ -1349,7 +1349,7 @@ impl Land {
dest: Vec2<i32>,
mut path_cost_fn: impl FnMut(Option<&Tile>, Option<&Tile>) -> f32,
) -> Option<Path<Vec2<i32>>> {
let heuristic = |pos: &Vec2<i32>| (pos - dest).map(|e| e as f32).magnitude();
let heuristic = |pos: &Vec2<i32>, _: &Vec2<i32>| (pos - dest).map(|e| e as f32).magnitude();
let neighbors = |pos: &Vec2<i32>| {
let pos = *pos;
CARDINALS.iter().map(move |dir| pos + *dir)
@ -1362,14 +1362,9 @@ impl Land {
// (1) we don't care about DDOS attacks (ruling out SipHash);
// (2) we don't care about determinism across computers (we could use AAHash);
// (3) we have 8-byte keys (for which FxHash is fastest).
Astar::new(
250,
origin,
heuristic,
BuildHasherDefault::<FxHasher64>::default(),
)
.poll(250, heuristic, neighbors, transition, satisfied)
.into_path()
Astar::new(250, origin, BuildHasherDefault::<FxHasher64>::default())
.poll(250, heuristic, neighbors, transition, satisfied)
.into_path()
}
/// We use this hasher (FxHasher64) because

View File

@ -146,7 +146,8 @@ impl Site {
) -> Option<Id<Plot>> {
const MAX_ITERS: usize = 4096;
let range = -(w as i32) / 2..w as i32 - (w as i32 + 1) / 2;
let heuristic = |tile: &Vec2<i32>| {
let heuristic = |(tile, dir): &(Vec2<i32>, Vec2<i32>),
(_, old_dir): &(Vec2<i32>, Vec2<i32>)| {
let mut max_cost = (tile.distance_squared(b) as f32).sqrt();
for y in range.clone() {
for x in range.clone() {
@ -157,35 +158,35 @@ impl Site {
}
}
}
max_cost
max_cost + (dir != old_dir) as i32 as f32 * 35.0
};
let path = Astar::new(MAX_ITERS, a, heuristic, DefaultHashBuilder::default())
let path = Astar::new(MAX_ITERS, (a, Vec2::zero()), DefaultHashBuilder::default())
.poll(
MAX_ITERS,
&heuristic,
|tile| {
|(tile, _)| {
let tile = *tile;
CARDINALS.iter().map(move |dir| tile + *dir)
CARDINALS.iter().map(move |dir| (tile + *dir, *dir))
},
|a, b| {
|(a, _), (b, _)| {
let alt_a = land.get_alt_approx(self.tile_center_wpos(*a));
let alt_b = land.get_alt_approx(self.tile_center_wpos(*b));
(alt_a - alt_b).abs() / TILE_SIZE as f32
},
|tile| *tile == b,
|(tile, _)| *tile == b,
)
.into_path()?;
let plot = self.create_plot(Plot {
kind: PlotKind::Road(path.clone()),
kind: PlotKind::Road(path.iter().map(|(tile, _)| *tile).collect()),
root_tile: a,
tiles: path.clone().into_iter().collect(),
tiles: path.iter().map(|(tile, _)| *tile).collect(),
seed: rng.gen(),
});
self.roads.push(plot);
for (i, &tile) in path.iter().enumerate() {
for (i, (tile, _)) in path.iter().enumerate() {
for y in range.clone() {
for x in range.clone() {
let tile = tile + Vec2::new(x, y);

View File

@ -543,7 +543,8 @@ impl Floor {
}
fn create_route(&mut self, _ctx: &mut GenCtx<impl Rng>, a: Vec2<i32>, b: Vec2<i32>) {
let heuristic = move |l: &Vec2<i32>| (l - b).map(|e| e.abs()).reduce_max() as f32;
let heuristic =
move |l: &Vec2<i32>, _: &Vec2<i32>| (l - b).map(|e| e.abs()).reduce_max() as f32;
let neighbors = |l: &Vec2<i32>| {
let l = *l;
CARDINALS
@ -562,12 +563,7 @@ impl Floor {
// (1) we don't care about DDOS attacks (ruling out SipHash);
// (2) we don't care about determinism across computers (we could use AAHash);
// (3) we have 8-byte keys (for which FxHash is fastest).
let mut astar = Astar::new(
20000,
a,
heuristic,
BuildHasherDefault::<FxHasher64>::default(),
);
let mut astar = Astar::new(20000, a, BuildHasherDefault::<FxHasher64>::default());
let path = astar
.poll(
FLOOR_SIZE.product() as usize + 1,