rustsim-core 0.0.1

Core ABM engine: agents, models, stores, schedulers, stepping, data collection
Documentation
use rand::rngs::StdRng;
use rand::SeedableRng;
use rustsim_core::{
    interaction::{self, InteractionError, PositionedAgent, SpaceInteraction},
    prelude::{Agent, Fastest, HashMapStore, StandardModel},
    types::AgentId,
};
mod support;
use support::{Grid2D, GridPos2};

#[derive(Debug, Clone)]
struct Bot {
    id: AgentId,
    pos: GridPos2,
}

impl Agent for Bot {
    fn id(&self) -> AgentId {
        self.id
    }
}

impl PositionedAgent for Bot {
    type Position = GridPos2;
    fn position(&self) -> &GridPos2 {
        &self.pos
    }
    fn set_position(&mut self, p: GridPos2) {
        self.pos = p;
    }
}

type BotModel = StandardModel<Grid2D, Bot, HashMapStore<Bot>, (), StdRng, Fastest>;

fn make_model() -> BotModel {
    BotModel::new(
        HashMapStore::new(),
        Grid2D::new(5, 5, false),
        Fastest::new(),
        (),
        StdRng::seed_from_u64(0),
        None,
        None,
        true,
    )
}

#[test]
fn add_duplicate_agent_returns_duplicate_id_error() {
    let mut model = make_model();
    let bot = Bot { id: 1, pos: (0, 0) };
    interaction::add_agent(&mut model, bot).unwrap();

    let dup = Bot { id: 1, pos: (1, 1) };
    let err = interaction::add_agent(&mut model, dup);
    assert!(matches!(err, Err(InteractionError::DuplicateId(1))));
}

#[test]
fn move_nonexistent_agent_returns_not_found() {
    let mut model = make_model();
    let err = interaction::move_agent(&mut model, 999, (2, 2));
    assert!(matches!(err, Err(InteractionError::AgentNotFound(999))));
}

#[test]
fn remove_nonexistent_agent_returns_none() {
    let mut model = make_model();
    let result = interaction::remove_agent(&mut model, 999).unwrap();
    assert!(result.is_none());
}

#[test]
fn add_agent_oob_position_returns_space_error() {
    let mut model = make_model();
    let bot = Bot {
        id: 1,
        pos: (99, 99),
    };
    let err = interaction::add_agent(&mut model, bot);
    assert!(matches!(err, Err(InteractionError::Space(_))));
    assert!(model.agent(1).is_none());
    assert!(interaction::all_ids(&model).is_empty());
}

#[test]
fn move_agent_to_oob_returns_space_error() {
    let mut model = make_model();
    let bot = Bot { id: 1, pos: (0, 0) };
    interaction::add_agent(&mut model, bot).unwrap();

    let err = interaction::move_agent(&mut model, 1, (99, 99));
    assert!(matches!(err, Err(InteractionError::Space(_))));
    assert_eq!(*model.agent(1).unwrap().position(), (0, 0));

    let old_cell_ids = <Grid2D as SpaceInteraction<Bot>>::nearby_ids(model.space(), &(0, 0), 0);
    assert_eq!(old_cell_ids, vec![1]);
}

#[test]
fn random_id_on_empty_model_returns_none() {
    let mut model = make_model();
    assert!(interaction::random_id(&mut model).is_none());
}

#[test]
fn random_agent_on_empty_model_returns_none() {
    let mut model = make_model();
    assert!(interaction::random_agent(&mut model).is_none());
}

#[test]
fn all_ids_on_empty_model_returns_empty() {
    let model = make_model();
    assert!(interaction::all_ids(&model).is_empty());
}