movingai

Crates.iomovingai
lib.rsmovingai
version1.3.1
sourcesrc
created_at2018-01-24 14:51:43.893795
updated_at2024-04-26 12:29:57.995697
descriptionMovingAI Benchmark Map/Scen File Parser
homepagehttps://github.com/THeK3nger/movingai-rust
repositoryhttps://github.com/THeK3nger/movingai-rust
max_upload_size
id48152
size834,930
owner (github:rust-iendo:owner)

documentation

README

movingai-rust

Cargo Version

Map/Scenario Parser for the MovingAI benchmark format. It offers a quick way to parse scenario and map files, with the addition of some utilities to manage and query information from the maps.

Map Features

The crate parses map and scene files and provides several function for easy interaction and query.

Some of the functionalities are:

  • Easy idiomatic access to the map data such as width, height and tiles at a specific coordinate.
  • Check if a tile is traversable or not according the MovingAI format rules.
  • Get the list of accessible neighbors from a specific tile.
  • [TO DO] Convert bitmaps into .map files.
  • Serialize/Deserialzie .map and .scen files into JSON/YAML using serde (activate --features serde)

How to use

extern crate movingai;

use std::path::Path;
use movingai::parser::parse_map_file;

fn main() {
    let map = parse_map_file(Path::new("./test/arena.map")).unwrap();
    let width = map.width();
    let tile = map[(4,5)]; // Access map location at row 4 and column 5.
}

As an example, you can see how we can use this crate to easily implement the A* pathfinding algorithm.

// A* shortest path algorithm.

fn shortest_path(map: &MovingAiMap, start: Coords2D, goal: Coords2D) -> Option<f64> {

    let mut heap = BinaryHeap::new();
    let mut visited = Vec::<Coords2D>::new();

    // We're at `start`, with a zero cost
    heap.push(SearchNode { f: 0.0, g:0.0, h: distance(start, goal), current: start });

    while let Some(SearchNode { f: _f, g, h: _h, current }) = heap.pop() {

        if current == goal { return Some(g); }

        if visited.contains(&current) {
            continue;
        }

        visited.push(current);

        for neigh in map.neighbors(current) {
            let new_h = distance(neigh, goal);
            let i = distance(neigh, current);
            let next = SearchNode { f: g+i+new_h, g: g+i, h: new_h, current: neigh };
            heap.push(next);
        }
    }

    // Goal not reachable
    None
}

And in this example we can see how to write a benchmark over a scen file.

fn main() {
    let map = parse_map_file(Path::new("./tests/arena.map")).unwrap();
    let scenes = parse_scen_file(Path::new("./tests/arena.map.scen")).unwrap();
    for scene in scenes {
        let start = scene.start_pos;
        let goal = scene.goal_pos;
        let t = Instant::now();
        match shortest_path(&map, (1,3), (4,3)) {
            Some(x) => {
                let duration = t.elapsed();
                let seconds = duration.as_secs();
                let ms = (duration.subsec_nanos() as f64) / 1_000_000.0;
                println!("{:?} -> {:?} \tin {:?} seconds and {:?} ms", start, goal, seconds, ms);
            }
            None => println!("None"),
        }
    }
}

Why cargo test is failing?

Note that tests need to be compiled with the serde feature enabled.

cargo test --feature=serde
Commit count: 112

cargo fmt