mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Cleanup
This commit is contained in:
parent
5486cc75e3
commit
cac425a62a
@ -34,90 +34,6 @@ impl<S: Eq> PartialOrd for PathEntry<S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reconstruct_path<S>(came_from: &HashMap<S, S>, target: &S) -> Vec<S>
|
|
||||||
where
|
|
||||||
S: Clone + Eq + Hash,
|
|
||||||
{
|
|
||||||
let mut path = Vec::new();
|
|
||||||
path.push(target.to_owned());
|
|
||||||
let mut cur_node = target;
|
|
||||||
while let Some(node) = came_from.get(cur_node) {
|
|
||||||
path.push(node.to_owned());
|
|
||||||
cur_node = node;
|
|
||||||
}
|
|
||||||
path
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn astar<S, I>(
|
|
||||||
initial: S,
|
|
||||||
target: S,
|
|
||||||
mut heuristic: impl FnMut(&S, &S) -> f32,
|
|
||||||
mut neighbors: impl FnMut(&S) -> I,
|
|
||||||
mut transition_cost: impl FnMut(&S, &S) -> f32,
|
|
||||||
) -> Option<Vec<S>>
|
|
||||||
where
|
|
||||||
S: Clone + Eq + Hash,
|
|
||||||
I: IntoIterator<Item = S>,
|
|
||||||
{
|
|
||||||
// Set of discovered nodes so far
|
|
||||||
let mut potential_nodes = BinaryHeap::new();
|
|
||||||
potential_nodes.push(PathEntry {
|
|
||||||
cost: 0.0f32,
|
|
||||||
node: initial.clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
// For entry e, contains the cheapest node preceding it on the known path from start to e
|
|
||||||
let mut came_from = HashMap::new();
|
|
||||||
|
|
||||||
// Contains cheapest cost from 'initial' to the current entry
|
|
||||||
let mut cheapest_scores = HashMap::new();
|
|
||||||
cheapest_scores.insert(initial.clone(), 0.0f32);
|
|
||||||
|
|
||||||
// Contains cheapest score to get to node + heuristic to the end, for an entry
|
|
||||||
let mut final_scores = HashMap::new();
|
|
||||||
final_scores.insert(initial.clone(), heuristic(&initial, &target));
|
|
||||||
|
|
||||||
// Set of nodes we have already visited
|
|
||||||
let mut visited = HashSet::new();
|
|
||||||
visited.insert(initial.clone());
|
|
||||||
|
|
||||||
let mut iters = 0;
|
|
||||||
while let Some(PathEntry { node: current, .. }) = potential_nodes.pop() {
|
|
||||||
if current == target {
|
|
||||||
return Some(reconstruct_path(&came_from, ¤t));
|
|
||||||
}
|
|
||||||
|
|
||||||
let current_neighbors = neighbors(¤t);
|
|
||||||
for neighbor in current_neighbors {
|
|
||||||
let current_cheapest_score = cheapest_scores.get(¤t).unwrap_or(&f32::MAX);
|
|
||||||
let neighbor_cheapest_score = cheapest_scores.get(&neighbor).unwrap_or(&f32::MAX);
|
|
||||||
let score = current_cheapest_score + transition_cost(¤t, &neighbor);
|
|
||||||
if score < *neighbor_cheapest_score {
|
|
||||||
// Path to the neighbor is better than anything yet recorded
|
|
||||||
came_from.insert(neighbor.to_owned(), current.to_owned());
|
|
||||||
cheapest_scores.insert(neighbor.clone(), score);
|
|
||||||
let neighbor_score = score + heuristic(&neighbor, &target);
|
|
||||||
final_scores.insert(neighbor.clone(), neighbor_score);
|
|
||||||
|
|
||||||
if visited.insert(neighbor.clone()) {
|
|
||||||
potential_nodes.push(PathEntry {
|
|
||||||
node: neighbor.clone(),
|
|
||||||
cost: neighbor_score,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iters += 1;
|
|
||||||
if iters >= 10000 {
|
|
||||||
println!("Ran out of turns!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum PathResult<T> {
|
pub enum PathResult<T> {
|
||||||
None(Path<T>),
|
None(Path<T>),
|
||||||
Exhausted(Path<T>),
|
Exhausted(Path<T>),
|
||||||
|
@ -94,9 +94,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(wander_pos) = wander_pos {
|
if let Some(wp) = wander_pos {
|
||||||
if let Some(bearing) = chaser.chase(&*terrain, pos.0, *wander_pos, 2.0)
|
if let Some(bearing) = chaser.chase(&*terrain, pos.0, *wp, 2.0) {
|
||||||
{
|
|
||||||
inputs.move_dir =
|
inputs.move_dir =
|
||||||
Vec2::from(bearing).try_normalized().unwrap_or(Vec2::zero());
|
Vec2::from(bearing).try_normalized().unwrap_or(Vec2::zero());
|
||||||
inputs.jump.set_state(bearing.z > 1.0);
|
inputs.jump.set_state(bearing.z > 1.0);
|
||||||
@ -227,153 +226,6 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
const PET_DIST: f32 = 6.0;
|
|
||||||
const MAX_PET_DIST: f32 = 16.0;
|
|
||||||
const PATROL_DIST: f32 = 32.0;
|
|
||||||
const SIGHT_DIST: f32 = 24.0;
|
|
||||||
const MIN_ATTACK_DIST: f32 = 3.25;
|
|
||||||
const CHASE_TIME_MIN: f64 = 4.0;
|
|
||||||
|
|
||||||
let mut chase_tgt = None;
|
|
||||||
let mut choose_target = false;
|
|
||||||
let mut new_target = None;
|
|
||||||
|
|
||||||
if let Some((target, aggro_time)) = agent.target {
|
|
||||||
// Chase / attack target
|
|
||||||
if let (Some(tgt_pos), stats) = (positions.get(target), stats.get(target)) {
|
|
||||||
if stats.map(|s| s.is_dead).unwrap_or(false) {
|
|
||||||
// Don't target dead entities
|
|
||||||
choose_target = true;
|
|
||||||
} else if pos.0.distance(tgt_pos.0) < SIGHT_DIST
|
|
||||||
|| (time.0 - aggro_time) < CHASE_TIME_MIN
|
|
||||||
{
|
|
||||||
chase_tgt = Some((tgt_pos.0, 1.5, true))
|
|
||||||
} else {
|
|
||||||
// Lose sight of enemies
|
|
||||||
choose_target = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
choose_target = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
choose_target = thread_rng().gen::<f32>() < 0.05;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return to owner
|
|
||||||
if let Some(owner) = agent.owner {
|
|
||||||
if let Some(tgt_pos) = positions.get(owner) {
|
|
||||||
let dist = pos.0.distance(tgt_pos.0);
|
|
||||||
if dist > MAX_PET_DIST || (dist > PET_DIST && agent.target.is_none()) {
|
|
||||||
// Follow owner
|
|
||||||
chase_tgt = Some((tgt_pos.0, 6.0, false));
|
|
||||||
} else if agent.target.is_none() {
|
|
||||||
choose_target = thread_rng().gen::<f32>() < 0.02;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
agent.owner = None;
|
|
||||||
}
|
|
||||||
} else if let Some(patrol_origin) = agent.patrol_origin {
|
|
||||||
if pos.0.distance(patrol_origin) > PATROL_DIST {
|
|
||||||
// Return to patrol origin
|
|
||||||
chase_tgt = Some((patrol_origin, 64.0, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attack a target that's attacking us
|
|
||||||
if let Some(stats) = stats.get(entity) {
|
|
||||||
match stats.health.last_change.1.cause {
|
|
||||||
comp::HealthSource::Attack { by } => {
|
|
||||||
if agent.target.is_none() {
|
|
||||||
new_target = uid_allocator.retrieve_entity_internal(by.id());
|
|
||||||
} else if thread_rng().gen::<f32>() < 0.005 {
|
|
||||||
new_target = uid_allocator.retrieve_entity_internal(by.id());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Choose a new target
|
|
||||||
if choose_target {
|
|
||||||
// Search for new targets
|
|
||||||
let entities = (&entities, &positions, &stats, alignments.maybe())
|
|
||||||
.join()
|
|
||||||
.filter(|(e, e_pos, e_stats, e_alignment)| {
|
|
||||||
(e_pos.0 - pos.0).magnitude() < SIGHT_DIST
|
|
||||||
&& *e != entity
|
|
||||||
&& !e_stats.is_dead
|
|
||||||
&& alignment
|
|
||||||
.and_then(|a| e_alignment.map(|b| a.hostile_towards(*b)))
|
|
||||||
.unwrap_or(false)
|
|
||||||
})
|
|
||||||
.map(|(e, _, _, _)| e)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
new_target = (&entities).choose(&mut thread_rng()).cloned();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update target when attack begins
|
|
||||||
match agent.target {
|
|
||||||
Some((tgt, time)) if Some(tgt) == new_target => {},
|
|
||||||
_ => agent.target = new_target.map(|tgt| (tgt, time.0))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chase target
|
|
||||||
if let Some((tgt_pos, min_dist, aggressive)) = chase_tgt {
|
|
||||||
if let Some(bearing) = agent.chaser.chase(&*terrain, pos.0, tgt_pos, min_dist) {
|
|
||||||
inputs.move_dir = Vec2::from(bearing).try_normalized().unwrap_or(Vec2::zero());
|
|
||||||
inputs.jump.set_state(bearing.z > 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if aggressive && pos.0.distance(tgt_pos) < MIN_ATTACK_DIST {
|
|
||||||
inputs.look_dir = tgt_pos - pos.0;
|
|
||||||
inputs.move_dir = Vec2::from(tgt_pos - pos.0)
|
|
||||||
.try_normalized()
|
|
||||||
.unwrap_or(Vec2::zero())
|
|
||||||
* 0.01;
|
|
||||||
inputs.primary.set_state(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're not wandering
|
|
||||||
agent.wander_pos = None;
|
|
||||||
} else {
|
|
||||||
if let Some(wander_pos) = agent.wander_pos {
|
|
||||||
if pos.0.distance(wander_pos) < 4.0 {
|
|
||||||
agent.wander_pos = None;
|
|
||||||
} else {
|
|
||||||
if let Some(bearing) = agent.chaser.chase(&*terrain, pos.0, wander_pos, 3.0)
|
|
||||||
{
|
|
||||||
inputs.move_dir =
|
|
||||||
Vec2::from(bearing).try_normalized().unwrap_or(Vec2::zero()) * 0.5;
|
|
||||||
inputs.jump.set_state(bearing.z > 1.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Choose new wander position
|
|
||||||
/*
|
|
||||||
if agent.wander_pos.is_none() || thread_rng().gen::<f32>() < 0.005 {
|
|
||||||
agent.wander_pos = if thread_rng().gen::<f32>() < 0.5 {
|
|
||||||
let max_dist = if agent.owner.is_some() {
|
|
||||||
PET_DIST
|
|
||||||
} else {
|
|
||||||
PATROL_DIST
|
|
||||||
};
|
|
||||||
Some(
|
|
||||||
agent
|
|
||||||
.patrol_origin
|
|
||||||
.unwrap_or(pos.0)
|
|
||||||
.map(|e| e + (thread_rng().gen::<f32>() - 0.5) * max_dist),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
debug_assert!(inputs.move_dir.map(|e| !e.is_nan()).reduce_and());
|
debug_assert!(inputs.move_dir.map(|e| !e.is_nan()).reduce_and());
|
||||||
debug_assert!(inputs.look_dir.map(|e| !e.is_nan()).reduce_and());
|
debug_assert!(inputs.look_dir.map(|e| !e.is_nan()).reduce_and());
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ use common::{
|
|||||||
npc::{get_npc_name, NpcKind},
|
npc::{get_npc_name, NpcKind},
|
||||||
state::TimeOfDay,
|
state::TimeOfDay,
|
||||||
sync::{Uid, WorldSyncExt},
|
sync::{Uid, WorldSyncExt},
|
||||||
terrain::{Block, BlockKind, TerrainChunkSize},
|
terrain::TerrainChunkSize,
|
||||||
vol::RectVolSize,
|
vol::RectVolSize,
|
||||||
};
|
};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use common::comp::{Player, Pos, Waypoint, WaypointArea};
|
use common::comp::{Player, Pos, Waypoint, WaypointArea};
|
||||||
use specs::{Entities, Join, Read, ReadStorage, System, Write, WriteStorage};
|
use specs::{Entities, Join, ReadStorage, System, WriteStorage};
|
||||||
|
|
||||||
/// This system will handle loading generated chunks and unloading uneeded chunks.
|
/// This system will handle loading generated chunks and unloading uneeded chunks.
|
||||||
/// 1. Inserts newly generated chunks into the TerrainGrid
|
/// 1. Inserts newly generated chunks into the TerrainGrid
|
||||||
|
Loading…
x
Reference in New Issue
Block a user