parent
f25b454c00
commit
56417cf9b4
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "mapgen-demo"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
authors = ["Krzysztof Langner <klangner@gmail.com>"]
|
||||
description = "Map generator demo"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -11,8 +11,9 @@ edition = "2018"
|
|||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
rand = { version = "0.7", features = ["wasm-bindgen"] }
|
||||
mapgen = {path=".."}
|
||||
getrandom = { version = "0.2", features = ["js"] }
|
||||
rand = "0.8"
|
||||
wasm-bindgen = "0.2"
|
||||
js-sys = "0.3"
|
||||
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Note the usage of `type=module` here as this is an ES6 module -->
|
||||
<script type="module">
|
||||
// Use ES module import syntax to import functionality from the module
|
||||
// that we have compiled.
|
||||
//
|
||||
// Note that the `default` import is an initialization function which
|
||||
// will "boot" the module and make it ready to use. Currently browsers
|
||||
// don't support natively imported WebAssembly as an ES module, but
|
||||
// eventually the manual initialization won't be required!
|
||||
import init, { add } from './pkg/mapgen_demo.js';
|
||||
|
||||
async function run() {
|
||||
// First up we need to actually load the wasm file, so we use the
|
||||
// default export to inform it where the wasm file is located on the
|
||||
// server, and then we wait on the returned promise to wait for the
|
||||
// wasm to be loaded.
|
||||
//
|
||||
// It may look like this: `await init('./pkg/without_a_bundler_bg.wasm');`,
|
||||
// but there is also a handy default inside `init` function, which uses
|
||||
// `import.meta` to locate the wasm file relatively to js file.
|
||||
//
|
||||
// Note that instead of a string you can also pass in any of the
|
||||
// following things:
|
||||
//
|
||||
// * `WebAssembly.Module`
|
||||
//
|
||||
// * `ArrayBuffer`
|
||||
//
|
||||
// * `Response`
|
||||
//
|
||||
// * `Promise` which returns any of the above, e.g. `fetch("./path/to/wasm")`
|
||||
//
|
||||
// This gives you complete control over how the module is loaded
|
||||
// and compiled.
|
||||
//
|
||||
// Also note that the promise, when resolved, yields the wasm module's
|
||||
// exports which is the same as importing the `*_bg` module in other
|
||||
// modes
|
||||
await init();
|
||||
|
||||
// And afterwards we can use all the functionality defined in wasm.
|
||||
const result = add(1, 2);
|
||||
console.log(`1 + 2 = ${result}`);
|
||||
if (result !== 3)
|
||||
throw new Error("wasm addition doesn't work!");
|
||||
}
|
||||
|
||||
run();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -3,6 +3,7 @@ use web_sys;
|
|||
use rand::prelude::*;
|
||||
use mapgen::{Map, MapBuilder, TileType, geometry::Point};
|
||||
use mapgen::filter::*;
|
||||
use mapgen::metric;
|
||||
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
@ -48,6 +49,7 @@ impl World {
|
|||
.with(CullUnreachable::new())
|
||||
.with(DistantExit::new())
|
||||
.build_with_rng(&mut rng);
|
||||
World::print_map_metrics(&map);
|
||||
World::new(width, height, map)
|
||||
}
|
||||
|
||||
|
@ -60,6 +62,7 @@ impl World {
|
|||
.with(AreaStartingPosition::new(XStart::LEFT, YStart::TOP))
|
||||
.with(DistantExit::new())
|
||||
.build_with_rng(&mut rng);
|
||||
World::print_map_metrics(&map);
|
||||
World::new(width, height, map)
|
||||
}
|
||||
|
||||
|
@ -72,6 +75,7 @@ impl World {
|
|||
.with(AreaStartingPosition::new(XStart::LEFT, YStart::BOTTOM))
|
||||
.with(DistantExit::new())
|
||||
.build_with_rng(&mut rng);
|
||||
World::print_map_metrics(&map);
|
||||
World::new(width, height, map)
|
||||
}
|
||||
|
||||
|
@ -84,6 +88,7 @@ impl World {
|
|||
.with(CullUnreachable::new())
|
||||
.with(DistantExit::new())
|
||||
.build_with_rng(&mut rng);
|
||||
World::print_map_metrics(&map);
|
||||
World::new(width, height, map)
|
||||
}
|
||||
|
||||
|
@ -96,6 +101,7 @@ impl World {
|
|||
.with(CullUnreachable::new())
|
||||
.with(DistantExit::new())
|
||||
.build_with_rng(&mut rng);
|
||||
World::print_map_metrics(&map);
|
||||
World::new(width, height, map)
|
||||
}
|
||||
|
||||
|
@ -107,6 +113,7 @@ impl World {
|
|||
.with(AreaStartingPosition::new(XStart::LEFT, YStart::TOP))
|
||||
.with(DistantExit::new())
|
||||
.build_with_rng(&mut rng);
|
||||
World::print_map_metrics(&map);
|
||||
World::new(width, height, map)
|
||||
}
|
||||
|
||||
|
@ -118,6 +125,7 @@ impl World {
|
|||
.with(AreaStartingPosition::new(XStart::LEFT, YStart::TOP))
|
||||
.with(DistantExit::new())
|
||||
.build_with_rng(&mut rng);
|
||||
World::print_map_metrics(&map);
|
||||
World::new(width, height, map)
|
||||
}
|
||||
|
||||
|
@ -167,6 +175,16 @@ impl World {
|
|||
let div = document.get_element_by_id("map-info").expect("Need div with id: map-info");
|
||||
div.set_inner_html(&info);
|
||||
}
|
||||
|
||||
fn print_map_metrics(map: &Map) {
|
||||
let window = web_sys::window().expect("no global `window` exists");
|
||||
let document = window.document().expect("should have a document on window");
|
||||
let div = document.get_element_by_id("map-metrics").expect("Need div with id: map-metrics");
|
||||
let density = metric::density(map);
|
||||
let path_length = metric::path_length(map);
|
||||
let info = format!("Metrics: density: {}, path length: {}", density, path_length);
|
||||
div.set_inner_html(&info);
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
|
||||
<canvas id="mapgen-canvas"></canvas>
|
||||
<div id="map-info" style="text-align: center"></div>
|
||||
<div id="map-metrics" style="text-align: center"></div>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
|
||||
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
|
||||
|
|
File diff suppressed because one or more lines are too long
BIN
docs/98c7bb1ad7a2b17fcade.module.wasm
Normal file
BIN
docs/98c7bb1ad7a2b17fcade.module.wasm
Normal file
Binary file not shown.
54
docs/bootstrap.js
vendored
54
docs/bootstrap.js
vendored
|
@ -58,33 +58,30 @@
|
|||
/******/ "__wbindgen_object_drop_ref": function(p0i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbindgen_object_drop_ref"](p0i32);
|
||||
/******/ },
|
||||
/******/ "__wbg_getRandomValues_3ac1b33c90b52596": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_getRandomValues_3ac1b33c90b52596"](p0i32,p1i32,p2i32);
|
||||
/******/ "__wbg_getRandomValues_c73f06b5ed8b878d": function(p0i32,p1i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_getRandomValues_c73f06b5ed8b878d"](p0i32,p1i32);
|
||||
/******/ },
|
||||
/******/ "__wbg_randomFillSync_6f956029658662ec": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_randomFillSync_6f956029658662ec"](p0i32,p1i32,p2i32);
|
||||
/******/ "__wbg_randomFillSync_5fa0a72035c7bfd9": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_randomFillSync_5fa0a72035c7bfd9"](p0i32,p1i32,p2i32);
|
||||
/******/ },
|
||||
/******/ "__wbg_self_1c83eb4471d9eb9b": function() {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_self_1c83eb4471d9eb9b"]();
|
||||
/******/ "__wbg_self_23b14d60c8dbf9da": function() {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_self_23b14d60c8dbf9da"]();
|
||||
/******/ },
|
||||
/******/ "__wbg_static_accessor_MODULE_abf5ae284bffdf45": function() {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_static_accessor_MODULE_abf5ae284bffdf45"]();
|
||||
/******/ "__wbg_static_accessor_MODULE_ff1e47f7076e0ee1": function() {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_static_accessor_MODULE_ff1e47f7076e0ee1"]();
|
||||
/******/ },
|
||||
/******/ "__wbg_require_5b2b5b594d809d9f": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_require_5b2b5b594d809d9f"](p0i32,p1i32,p2i32);
|
||||
/******/ "__wbg_require_1dab18ea211c4fa1": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_require_1dab18ea211c4fa1"](p0i32,p1i32,p2i32);
|
||||
/******/ },
|
||||
/******/ "__wbg_crypto_c12f14e810edcaa2": function(p0i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_crypto_c12f14e810edcaa2"](p0i32);
|
||||
/******/ "__wbg_crypto_df96f3577c8a9bae": function(p0i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_crypto_df96f3577c8a9bae"](p0i32);
|
||||
/******/ },
|
||||
/******/ "__wbg_msCrypto_679be765111ba775": function(p0i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_msCrypto_679be765111ba775"](p0i32);
|
||||
/******/ "__wbg_msCrypto_331efcdb9be40d7c": function(p0i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_msCrypto_331efcdb9be40d7c"](p0i32);
|
||||
/******/ },
|
||||
/******/ "__wbindgen_is_undefined": function(p0i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbindgen_is_undefined"](p0i32);
|
||||
/******/ },
|
||||
/******/ "__wbg_getRandomValues_05a60bf171bfc2be": function(p0i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_getRandomValues_05a60bf171bfc2be"](p0i32);
|
||||
/******/ },
|
||||
/******/ "__wbg_instanceof_Window_adf3196bdc02b386": function(p0i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_instanceof_Window_adf3196bdc02b386"](p0i32);
|
||||
/******/ },
|
||||
|
@ -118,8 +115,29 @@
|
|||
/******/ "__wbg_global_e16303fe83e1d57f": function() {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_global_e16303fe83e1d57f"]();
|
||||
/******/ },
|
||||
/******/ "__wbg_buffer_49131c283a06686f": function(p0i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_buffer_49131c283a06686f"](p0i32);
|
||||
/******/ },
|
||||
/******/ "__wbg_length_2b13641a9d906653": function(p0i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_length_2b13641a9d906653"](p0i32);
|
||||
/******/ },
|
||||
/******/ "__wbg_new_9b295d24cf1d706f": function(p0i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_new_9b295d24cf1d706f"](p0i32);
|
||||
/******/ },
|
||||
/******/ "__wbg_set_3bb960a9975f3cd2": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_set_3bb960a9975f3cd2"](p0i32,p1i32,p2i32);
|
||||
/******/ },
|
||||
/******/ "__wbg_newwithlength_3c570aeea9a95954": function(p0i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_newwithlength_3c570aeea9a95954"](p0i32);
|
||||
/******/ },
|
||||
/******/ "__wbg_subarray_4eaeb3de00cf1955": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_subarray_4eaeb3de00cf1955"](p0i32,p1i32,p2i32);
|
||||
/******/ },
|
||||
/******/ "__wbindgen_throw": function(p0i32,p1i32) {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbindgen_throw"](p0i32,p1i32);
|
||||
/******/ },
|
||||
/******/ "__wbindgen_memory": function() {
|
||||
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbindgen_memory"]();
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
|
@ -222,7 +240,7 @@
|
|||
/******/ promises.push(installedWasmModuleData);
|
||||
/******/ else {
|
||||
/******/ var importObject = wasmImportObjects[wasmModuleId]();
|
||||
/******/ var req = fetch(__webpack_require__.p + "" + {"../pkg/mapgen_demo_bg.wasm":"f22182091a16774e383e"}[wasmModuleId] + ".module.wasm");
|
||||
/******/ var req = fetch(__webpack_require__.p + "" + {"../pkg/mapgen_demo_bg.wasm":"98c7bb1ad7a2b17fcade"}[wasmModuleId] + ".module.wasm");
|
||||
/******/ var promise;
|
||||
/******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {
|
||||
/******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
|
||||
<canvas id="mapgen-canvas"></canvas>
|
||||
<div id="map-info" style="text-align: center"></div>
|
||||
<div id="map-metrics" style="text-align: center"></div>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
|
||||
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
pub mod filter;
|
||||
pub mod geometry;
|
||||
pub mod map;
|
||||
pub mod metric;
|
||||
|
||||
pub use map::{Map, Symmetry, TileType};
|
||||
pub use filter::*;
|
||||
|
|
95
src/metric.rs
Normal file
95
src/metric.rs
Normal file
|
@ -0,0 +1,95 @@
|
|||
//! Different metrics for the map
|
||||
//! Can be used to meausre the quality of the map or the quality of the generator.
|
||||
//! To meause the quality of the generator; generate lots of maps, measure them
|
||||
//! and the provide generator score as an average.
|
||||
//!
|
||||
|
||||
use super::map::{Map, TileType};
|
||||
use super::dijkstra::DijkstraMap;
|
||||
|
||||
|
||||
/// This metric calculates the percentage of walkable cells (Floor).
|
||||
/// If this number is very low (like < 10%) then it means that the map
|
||||
/// is probably to degenerated and shouldn't be used
|
||||
pub fn density(map: &Map) -> f32 {
|
||||
let floor_count = map.tiles.iter()
|
||||
.filter(|&t| *t == TileType::Floor)
|
||||
.count();
|
||||
floor_count as f32 / map.tiles.len() as f32
|
||||
}
|
||||
|
||||
|
||||
/// Calculate the length of the shortes path from the starting point
|
||||
/// to the exit.
|
||||
/// If this path is very short, then the map is probably degenerated.
|
||||
pub fn path_length(map: &Map) -> f32 {
|
||||
if map.starting_point.is_none() {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
match map.exit_point {
|
||||
None => 0.0,
|
||||
Some(exit) => {
|
||||
let dijkstra = DijkstraMap::new(map);
|
||||
dijkstra.tiles[map.xy_idx(exit.x, exit.y)]
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// ------------------------------------------------------------------------------------------------
|
||||
/// Module unit tests
|
||||
/// ------------------------------------------------------------------------------------------------
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::geometry::Point;
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_density_no_floor() {
|
||||
let map = Map::new(10, 10);
|
||||
let score = density(&map);
|
||||
assert_eq!(score, 0.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_density() {
|
||||
let map_str = "
|
||||
##########
|
||||
# ## #
|
||||
##########
|
||||
";
|
||||
let map = Map::from_string(map_str);
|
||||
let score = density(&map);
|
||||
assert_eq!(score, 0.2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_path() {
|
||||
let map_str = "
|
||||
##########
|
||||
# ## #
|
||||
##########
|
||||
";
|
||||
let map = Map::from_string(map_str);
|
||||
let score = path_length(&map);
|
||||
assert_eq!(score, 0.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_path_length() {
|
||||
let map_str = "
|
||||
##########
|
||||
# ## #
|
||||
# #
|
||||
##########
|
||||
";
|
||||
let mut map = Map::from_string(map_str);
|
||||
map.starting_point = Some(Point::new(1,1));
|
||||
map.exit_point = Some(Point::new(8,1));
|
||||
|
||||
let score = path_length(&map);
|
||||
assert!(f32::abs(score - 7.9) <= 0.01);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user