Let all agents move at the same time
This commit is contained in:
parent
adbf3b4e56
commit
5e6177900e
2 changed files with 59 additions and 30 deletions
|
|
@ -44,11 +44,13 @@ fn main() {
|
||||||
.draw(
|
.draw(
|
||||||
gen,
|
gen,
|
||||||
world
|
world
|
||||||
|
.state
|
||||||
.agent_positions
|
.agent_positions
|
||||||
.get(&world.tagged)
|
.get(&world.state.tagged)
|
||||||
.map(|pos| (pos.x, pos.y))
|
.map(|pos| (pos.x, pos.y))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
world
|
world
|
||||||
|
.state
|
||||||
.agent_positions
|
.agent_positions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_id, pos)| (pos.x, pos.y))
|
.map(|(_id, pos)| (pos.x, pos.y))
|
||||||
|
|
|
||||||
85
src/world.rs
85
src/world.rs
|
|
@ -1,10 +1,14 @@
|
||||||
use crate::agent::{Agent, AgentId, Direction, Move, Position, WorldView};
|
use crate::agent::{Agent, AgentId, Direction, Move, Position, WorldView};
|
||||||
use std::collections::hash_map::{Entry, HashMap};
|
use std::collections::hash_map::HashMap;
|
||||||
|
|
||||||
pub struct ActualWorld {
|
pub struct ActualWorld {
|
||||||
size: Position,
|
size: Position,
|
||||||
pub agent_positions: HashMap<AgentId, Position>,
|
|
||||||
pub agents: HashMap<AgentId, Box<dyn Agent>>,
|
pub agents: HashMap<AgentId, Box<dyn Agent>>,
|
||||||
|
pub state: WorldState,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WorldState {
|
||||||
|
pub agent_positions: HashMap<AgentId, Position>,
|
||||||
pub tagged: AgentId,
|
pub tagged: AgentId,
|
||||||
pub tagged_by: Option<AgentId>,
|
pub tagged_by: Option<AgentId>,
|
||||||
}
|
}
|
||||||
|
|
@ -23,12 +27,15 @@ impl ActualWorld {
|
||||||
agents.insert(id, agent);
|
agents.insert(id, agent);
|
||||||
id += 1;
|
id += 1;
|
||||||
}
|
}
|
||||||
Self {
|
let state = WorldState {
|
||||||
size,
|
|
||||||
tagged_by: None,
|
tagged_by: None,
|
||||||
tagged: id - 1,
|
tagged: id - 1,
|
||||||
agents,
|
|
||||||
agent_positions,
|
agent_positions,
|
||||||
|
};
|
||||||
|
Self {
|
||||||
|
size,
|
||||||
|
agents,
|
||||||
|
state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,15 +44,16 @@ impl ActualWorld {
|
||||||
.agents
|
.agents
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(id, agent)| {
|
.map(|(id, agent)| {
|
||||||
let pos = self.agent_positions.get(id).unwrap();
|
let pos = self.state.agent_positions.get(id).unwrap();
|
||||||
(
|
(
|
||||||
*id,
|
*id,
|
||||||
agent.next_move(WorldView {
|
agent.next_move(WorldView {
|
||||||
self_id: *id,
|
self_id: *id,
|
||||||
tagged_by: self.tagged_by,
|
tagged_by: self.state.tagged_by,
|
||||||
tagged: self.tagged,
|
tagged: self.state.tagged,
|
||||||
bounds_distance: (pos.y, self.size.x - pos.x, self.size.y - pos.y, pos.x),
|
bounds_distance: (pos.y, self.size.x - pos.x, self.size.y - pos.y, pos.x),
|
||||||
other_agents: self
|
other_agents: self
|
||||||
|
.state
|
||||||
.agent_positions
|
.agent_positions
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(other_id, _)| id != *other_id)
|
.filter(|(other_id, _)| id != *other_id)
|
||||||
|
|
@ -63,35 +71,54 @@ impl ActualWorld {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
let mut new_state = WorldState {
|
||||||
|
agent_positions: HashMap::with_capacity(self.state.agent_positions.len()),
|
||||||
|
tagged: self.state.tagged,
|
||||||
|
tagged_by: self.state.tagged_by,
|
||||||
|
};
|
||||||
for (id, mv) in moves {
|
for (id, mv) in moves {
|
||||||
|
self.check_move(id, &mv);
|
||||||
|
//println!("{} {:?}", id, mv);
|
||||||
|
let mut new_pos = None;
|
||||||
match mv {
|
match mv {
|
||||||
Move::Noop => {}
|
Move::Noop => {}
|
||||||
Move::TryTag(other_id) => {
|
Move::TryTag(other_id) => {
|
||||||
// FIXME check distance
|
new_state.tagged = other_id;
|
||||||
assert_eq!(self.tagged, id);
|
new_state.tagged_by = Some(id);
|
||||||
assert_ne!(self.tagged_by, Some(other_id));
|
|
||||||
assert!(
|
|
||||||
self.agents.contains_key(&other_id),
|
|
||||||
"Trying to tag a nonexisting agent"
|
|
||||||
);
|
|
||||||
self.tagged = other_id;
|
|
||||||
self.tagged_by = Some(id);
|
|
||||||
}
|
}
|
||||||
Move::TryMove(dir) => {
|
Move::TryMove(dir) => {
|
||||||
// FIXME check speed
|
let pos = self.state.agent_positions.get(&id).unwrap();
|
||||||
let entry = self.agent_positions.entry(id);
|
new_pos = Some((pos.x + dir.x, pos.y + dir.y).into());
|
||||||
let size = &self.size;
|
|
||||||
assert!(matches!(entry, Entry::Occupied(_)));
|
|
||||||
entry.and_modify(|e| {
|
|
||||||
e.x += dir.x;
|
|
||||||
assert!(e.x > 0);
|
|
||||||
assert!(e.x < size.x);
|
|
||||||
e.y += dir.y;
|
|
||||||
assert!(e.y > 0);
|
|
||||||
assert!(e.y < size.y);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
new_state.agent_positions.insert(
|
||||||
|
id,
|
||||||
|
new_pos.unwrap_or_else(|| self.state.agent_positions.remove(&id).unwrap()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
self.state = new_state;
|
||||||
|
}
|
||||||
|
fn check_move(&self, id: AgentId, mv: &Move) {
|
||||||
|
match mv {
|
||||||
|
Move::Noop => {}
|
||||||
|
Move::TryTag(other_id) => {
|
||||||
|
// FIXME check distance
|
||||||
|
assert_eq!(self.state.tagged, id);
|
||||||
|
assert_ne!(self.state.tagged_by, Some(*other_id));
|
||||||
|
assert!(
|
||||||
|
self.agents.contains_key(&other_id),
|
||||||
|
"Trying to tag a nonexisting agent"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Move::TryMove(dir) => {
|
||||||
|
// FIXME check speed
|
||||||
|
let pos = self.state.agent_positions.get(&id).unwrap();
|
||||||
|
let size = &self.size;
|
||||||
|
assert!(pos.x + dir.x > 0);
|
||||||
|
assert!(pos.x + dir.x < size.x);
|
||||||
|
assert!(pos.y + dir.y > 0);
|
||||||
|
assert!(pos.y + dir.y < size.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue