You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
2.2 KiB
122 lines
2.2 KiB
pub type Distance = isize;
|
|
|
|
pub struct Position {
|
|
pub x: Distance,
|
|
pub y: Distance,
|
|
}
|
|
|
|
impl From<(Distance, Distance)> for Position {
|
|
fn from((x, y): (Distance, Distance)) -> Self {
|
|
Self { x, y }
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Direction {
|
|
pub x: Distance,
|
|
pub y: Distance,
|
|
}
|
|
|
|
impl From<(Distance, Distance)> for Direction {
|
|
fn from((x, y): (Distance, Distance)) -> Self {
|
|
Self { x, y }
|
|
}
|
|
}
|
|
|
|
pub type AgentId = usize;
|
|
|
|
pub struct WorldView {
|
|
pub self_id: AgentId,
|
|
pub tagged: AgentId,
|
|
pub tagged_by: Option<AgentId>,
|
|
pub bounds_distance: (Distance, Distance, Distance, Distance),
|
|
pub other_agents: Vec<(Direction, AgentId)>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum Move {
|
|
Noop, // Why not an Option?
|
|
TryTag(AgentId),
|
|
TryMove(Direction),
|
|
}
|
|
|
|
pub trait Agent {
|
|
fn next_move(&self, view: WorldView) -> Move;
|
|
}
|
|
|
|
pub struct NullAgent;
|
|
|
|
impl Agent for NullAgent {
|
|
fn next_move(&self, _view: WorldView) -> Move {
|
|
Move::Noop
|
|
}
|
|
}
|
|
|
|
use std::cell::RefCell;
|
|
|
|
pub struct ScriptedAgent {
|
|
moves: RefCell<Vec<Move>>,
|
|
}
|
|
|
|
impl ScriptedAgent {
|
|
pub fn new(mut moves: Vec<Move>) -> Self {
|
|
moves.reverse();
|
|
Self {
|
|
moves: RefCell::new(moves),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Agent for ScriptedAgent {
|
|
fn next_move(&self, _view: WorldView) -> Move {
|
|
self
|
|
.moves
|
|
.borrow_mut()
|
|
.pop()
|
|
.expect("ScriptedAgent has no moves left to make")
|
|
}
|
|
}
|
|
|
|
pub struct SimpleAgent;
|
|
|
|
fn rand(exclusive_upper_bound: u32) -> u32 {
|
|
std::time::SystemTime::now()
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
.unwrap()
|
|
.subsec_micros()
|
|
% exclusive_upper_bound
|
|
}
|
|
|
|
fn random_move() -> Move {
|
|
Move::TryMove(
|
|
match rand(8) {
|
|
0 => (-1, -1),
|
|
1 => (0, -1),
|
|
2 => (1, -1),
|
|
3 => (1, 0),
|
|
4 => (1, 1),
|
|
5 => (0, 1),
|
|
6 => (-1, 1),
|
|
7 => (-1, 0),
|
|
_ => unreachable!(),
|
|
}
|
|
.into(),
|
|
)
|
|
}
|
|
|
|
impl Agent for SimpleAgent {
|
|
fn next_move(&self, view: WorldView) -> Move {
|
|
if view.self_id == view.tagged {
|
|
match view
|
|
.other_agents
|
|
.iter()
|
|
.find(|(dist, id)| dist.x.abs() <= 1 && dist.y.abs() <= 1 && Some(*id) != view.tagged_by)
|
|
{
|
|
Some((_, other)) => Move::TryTag(*other),
|
|
None => random_move(),
|
|
}
|
|
} else {
|
|
random_move()
|
|
}
|
|
}
|
|
}
|