multilinear 0.6.0

Interactive story simulation using constrained parallel aspects
Documentation
use event_simulation::{Simulation, SimulationState};
use multilinear::{Change, MultilinearInfo, MultilinearSimulation};

#[test]
fn test_simulation_events_without_changes() {
    let mut info = MultilinearInfo::new();
    info.add_aspect();

    let event1 = info.add_event().with_change(&[]).unwrap().event();
    let event2 = info.add_event().with_change(&[]).unwrap().event();

    let mut simulation = MultilinearSimulation::new(info);
    assert_eq!(simulation.data(), vec![0]);

    assert!(simulation.try_call(event1));
    assert_eq!(simulation.data(), vec![0]);

    assert!(simulation.try_call(event2));
    assert_eq!(simulation.data(), vec![0]);

    assert!(simulation.try_revert(event2));
    assert_eq!(simulation.data(), vec![0]);

    assert!(simulation.try_revert(event1));
    assert_eq!(simulation.data(), vec![0]);
}

#[test]
fn test_simulation_linear() {
    let mut info = MultilinearInfo::new();
    let aspect = info.add_aspect();

    let change1 = vec![Change::transition(aspect, 0, 1)];
    let change2 = vec![Change::transition(aspect, 1, 2)];
    let change3 = vec![Change::transition(aspect, 2, 3)];
    let change4 = vec![Change::transition(aspect, 3, 4)];
    let change5 = vec![Change::transition(aspect, 4, 5)];

    let event1 = info.add_event().with_change(&change1).unwrap().event();
    let event2 = info.add_event().with_change(&change2).unwrap().event();
    let event3 = info.add_event().with_change(&change3).unwrap().event();
    let event4 = info.add_event().with_change(&change4).unwrap().event();
    let event5 = info.add_event().with_change(&change5).unwrap().event();

    let mut simulation = MultilinearSimulation::new(info);
    assert_eq!(simulation.data(), vec![0]);

    assert!(simulation.try_call(event1));
    assert_eq!(simulation.data(), vec![1]);

    assert!(simulation.try_call(event2));
    assert_eq!(simulation.data(), vec![2]);

    assert!(simulation.try_call(event3));
    assert_eq!(simulation.data(), vec![3]);

    assert!(simulation.try_call(event4));
    assert_eq!(simulation.data(), vec![4]);

    assert!(simulation.try_call(event5));
    assert_eq!(simulation.data(), vec![5]);

    assert!(simulation.try_revert(event5));
    assert_eq!(simulation.data(), vec![4]);

    assert!(simulation.try_revert(event4));
    assert_eq!(simulation.data(), vec![3]);

    assert!(simulation.try_revert(event3));
    assert_eq!(simulation.data(), vec![2]);

    assert!(simulation.try_revert(event2));
    assert_eq!(simulation.data(), vec![1]);

    assert!(simulation.try_revert(event1));
    assert_eq!(simulation.data(), vec![0]);
}

#[test]
fn test_simulation_linear_count() {
    let mut info = MultilinearInfo::new();
    let aspect = info.add_aspect();

    let change1 = vec![Change::transition(aspect, 0, 1)];
    let change2 = vec![Change::transition(aspect, 1, 2)];
    let change3 = vec![Change::transition(aspect, 2, 3)];
    let change4 = vec![Change::transition(aspect, 3, 4)];
    let change5 = vec![Change::transition(aspect, 4, 5)];

    let event = info
        .add_event()
        .with_change(&change1)
        .unwrap()
        .with_change(&change2)
        .unwrap()
        .with_change(&change3)
        .unwrap()
        .with_change(&change4)
        .unwrap()
        .with_change(&change5)
        .unwrap()
        .event();

    let mut simulation = MultilinearSimulation::new(info);
    assert_eq!(simulation.data(), vec![0]);

    assert!(simulation.try_call(event));
    assert_eq!(simulation.data(), vec![1]);

    assert!(simulation.try_call(event));
    assert_eq!(simulation.data(), vec![2]);

    assert!(simulation.try_call(event));
    assert_eq!(simulation.data(), vec![3]);

    assert!(simulation.try_call(event));
    assert_eq!(simulation.data(), vec![4]);

    assert!(simulation.try_call(event));
    assert_eq!(simulation.data(), vec![5]);

    assert!(simulation.try_revert(event));
    assert_eq!(simulation.data(), vec![4]);

    assert!(simulation.try_revert(event));
    assert_eq!(simulation.data(), vec![3]);

    assert!(simulation.try_revert(event));
    assert_eq!(simulation.data(), vec![2]);

    assert!(simulation.try_revert(event));
    assert_eq!(simulation.data(), vec![1]);

    assert!(simulation.try_revert(event));
    assert_eq!(simulation.data(), vec![0]);
}

#[test]
fn test_simulation_branching() {
    let mut info = MultilinearInfo::new();
    let aspect = info.add_aspect();

    let change_start_to_left = vec![Change::transition(aspect, 0, 1)];
    let change_start_to_right = vec![Change::transition(aspect, 0, 2)];
    let change_right_to_end = vec![Change::transition(aspect, 2, 3)];
    let change_left_to_end = vec![Change::transition(aspect, 1, 3)];

    let event_start_to_left = info
        .add_event()
        .with_change(&change_start_to_left)
        .unwrap()
        .event();

    let event_start_to_right = info
        .add_event()
        .with_change(&change_start_to_right)
        .unwrap()
        .event();

    let event_right_to_end = info
        .add_event()
        .with_change(&change_right_to_end)
        .unwrap()
        .event();

    let event_left_to_end = info
        .add_event()
        .with_change(&change_left_to_end)
        .unwrap()
        .event();

    let mut simulation = MultilinearSimulation::new(info);
    assert_eq!(simulation.data(), vec![0]);

    assert!(simulation.try_call(event_start_to_left));
    assert_eq!(simulation.data(), vec![1]);
    assert!(simulation.try_call(event_left_to_end));
    assert_eq!(simulation.data(), vec![3]);
    assert!(simulation.try_revert(event_right_to_end));
    assert_eq!(simulation.data(), vec![2]);
    assert!(simulation.try_revert(event_start_to_right));
    assert_eq!(simulation.data(), vec![0]);

    assert!(simulation.try_call(event_start_to_right));
    assert_eq!(simulation.data(), vec![2]);
    assert!(simulation.try_call(event_right_to_end));
    assert_eq!(simulation.data(), vec![3]);
    assert!(simulation.try_revert(event_left_to_end));
    assert_eq!(simulation.data(), vec![1]);
    assert!(simulation.try_revert(event_start_to_left));
    assert_eq!(simulation.data(), vec![0]);
}

#[test]
fn test_simulation_back_forth() {
    let mut info = MultilinearInfo::new();
    let aspect = info.add_aspect();

    let change1 = vec![Change::transition(aspect, 0, 1)];
    let change2 = vec![Change::transition(aspect, 1, 0)];

    let event1 = info.add_event().with_change(&change1).unwrap().event();
    let event2 = info.add_event().with_change(&change2).unwrap().event();

    let mut simulation = MultilinearSimulation::new(info);
    assert_eq!(simulation.data(), vec![0]);

    assert!(!simulation.try_call(event2));
    assert!(simulation.try_call(event1));
    assert_eq!(simulation.data(), vec![1]);

    assert!(!simulation.try_call(event1));
    assert!(simulation.try_call(event2));
    assert_eq!(simulation.data(), vec![0]);

    assert!(!simulation.try_revert(event1));
    assert!(simulation.try_revert(event2));
    assert_eq!(simulation.data(), vec![1]);

    assert!(!simulation.try_revert(event2));
    assert!(simulation.try_revert(event1));
    assert_eq!(simulation.data(), vec![0]);
}

#[test]
fn test_simulation_multiple_aspects_same() {
    let mut info = MultilinearInfo::new();
    let aspect1 = info.add_aspect();
    let aspect2 = info.add_aspect();

    let change1 = vec![
        Change::transition(aspect1, 0, 1),
        Change::transition(aspect2, 0, 1),
    ];
    let change2 = vec![
        Change::transition(aspect1, 1, 2),
        Change::transition(aspect2, 1, 2),
    ];

    let event1 = info.add_event().with_change(&change1).unwrap().event();
    let event2 = info.add_event().with_change(&change2).unwrap().event();

    let mut simulation = MultilinearSimulation::new(info);
    assert_eq!(simulation.data(), vec![0, 0]);

    assert!(simulation.try_call(event1));
    assert_eq!(simulation.data(), vec![1, 1]);

    assert!(simulation.try_call(event2));
    assert_eq!(simulation.data(), vec![2, 2]);

    assert!(simulation.try_revert(event2));
    assert_eq!(simulation.data(), vec![1, 1]);

    assert!(simulation.try_revert(event1));
    assert_eq!(simulation.data(), vec![0, 0]);
}

#[test]
fn test_simulation_multiple_aspects() {
    let mut info = MultilinearInfo::new();
    let aspect1 = info.add_aspect();
    let aspect2 = info.add_aspect();
    let aspect3 = info.add_aspect();

    let change1 = vec![
        Change::transition(aspect1, 0, 1),
        Change::condition(aspect2, 0),
        Change::transition(aspect3, 0, 1),
    ];
    let change2 = vec![
        Change::transition(aspect1, 1, 2),
        Change::transition(aspect3, 1, 0),
    ];
    let change3 = vec![
        Change::transition(aspect1, 2, 3),
        Change::transition(aspect2, 0, 1),
        Change::condition(aspect3, 0),
    ];

    let event1 = info.add_event().with_change(&change1).unwrap().event();
    let event2 = info.add_event().with_change(&change2).unwrap().event();
    let event3 = info.add_event().with_change(&change3).unwrap().event();

    let mut simulation = MultilinearSimulation::new(info);
    assert_eq!(simulation.data(), vec![0, 0, 0]);

    assert!(simulation.try_call(event1));
    assert_eq!(simulation.data(), vec![1, 0, 1]);

    assert!(simulation.try_call(event2));
    assert_eq!(simulation.data(), vec![2, 0, 0]);

    assert!(simulation.try_call(event3));
    assert_eq!(simulation.data(), vec![3, 1, 0]);

    assert!(simulation.try_revert(event3));
    assert_eq!(simulation.data(), vec![2, 0, 0]);

    assert!(simulation.try_revert(event2));
    assert_eq!(simulation.data(), vec![1, 0, 1]);

    assert!(simulation.try_revert(event1));
    assert_eq!(simulation.data(), vec![0, 0, 0]);
}

#[test]
fn test_simulation_change_triangle() {
    let mut info = MultilinearInfo::new();
    let aspect1 = info.add_aspect();
    let aspect2 = info.add_aspect();
    let aspect3 = info.add_aspect();

    let change1 = vec![
        Change::transition(aspect1, 0, 1),
        Change::transition(aspect2, 0, 1),
    ];
    let change2 = vec![
        Change::transition(aspect2, 1, 0),
        Change::transition(aspect3, 0, 1),
    ];
    let change3 = vec![
        Change::transition(aspect3, 1, 0),
        Change::transition(aspect1, 1, 0),
    ];

    let event = info
        .add_event()
        .with_change(&change1)
        .unwrap()
        .with_change(&change2)
        .unwrap()
        .with_change(&change3)
        .unwrap()
        .event();

    let mut simulation = MultilinearSimulation::new(info);
    assert_eq!(simulation.data(), vec![0, 0, 0]);

    assert!(simulation.try_call(event));
    assert_eq!(simulation.data(), vec![1, 1, 0]);

    assert!(simulation.try_call(event));
    assert_eq!(simulation.data(), vec![1, 0, 1]);

    assert!(simulation.try_call(event));
    assert_eq!(simulation.data(), vec![0, 0, 0]);
}