2026-06-16 00:01:02 -05:00
|
|
|
|
mod fill_sparse;
|
2026-06-07 00:46:38 -05:00
|
|
|
|
mod grid_errors;
|
|
|
|
|
|
mod object_placement;
|
|
|
|
|
|
mod player_placement;
|
2026-06-13 16:24:29 -05:00
|
|
|
|
mod portal_placement;
|
2026-06-16 14:34:42 -05:00
|
|
|
|
mod pushers;
|
2026-06-07 00:46:38 -05:00
|
|
|
|
mod round_trip;
|
2026-06-21 01:32:47 -05:00
|
|
|
|
mod spinners;
|
2026-07-08 10:06:25 -05:00
|
|
|
|
mod transporters;
|
2026-06-07 00:46:38 -05:00
|
|
|
|
|
|
|
|
|
|
use crate::board::Board;
|
|
|
|
|
|
use crate::map_file::MapFile;
|
|
|
|
|
|
|
|
|
|
|
|
fn load_board(toml: &str) -> Board {
|
|
|
|
|
|
let mf: MapFile = toml::from_str(toml).expect("parse toml");
|
|
|
|
|
|
Board::try_from(mf).expect("convert to board")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-10 23:16:28 -05:00
|
|
|
|
/// Builds the `[grid]` block: a triple-quoted `content` grid plus an inline
|
2026-06-15 23:35:18 -05:00
|
|
|
|
/// `palette` table. Each palette entry is `(char_key, inline-body)` where the
|
|
|
|
|
|
/// body is the inside of the entry's `{ ... }` (e.g. `kind = "wall"`).
|
2026-07-10 23:16:28 -05:00
|
|
|
|
fn grid(content: &str, palette: &[(&str, &str)]) -> String {
|
2026-06-15 23:35:18 -05:00
|
|
|
|
let pal = palette
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
.map(|(k, body)| format!("\"{k}\" = {{ {body} }}"))
|
|
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
|
|
.join(", ");
|
2026-07-10 23:16:28 -05:00
|
|
|
|
format!("\n[grid]\ncontent = \"\"\"\n{content}\n\"\"\"\npalette = {{ {pal} }}\n")
|
2026-06-07 00:46:38 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-10 23:16:28 -05:00
|
|
|
|
/// Wraps a `[map]` header of the given size around the single `[grid]` block
|
|
|
|
|
|
/// (produced by [`grid`]).
|
|
|
|
|
|
fn map(width: usize, height: usize, grid_block: &str) -> String {
|
|
|
|
|
|
format!("[map]\nname = \"Test\"\nwidth = {width}\nheight = {height}\n{grid_block}")
|
2026-06-07 00:46:38 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-15 23:35:18 -05:00
|
|
|
|
/// A 3×1 single-layer map: an `empty`/`wall` palette plus one `object` entry
|
|
|
|
|
|
/// placed by char `ch` (cyan `@` glyph), with `extra` appended to its body. The
|
|
|
|
|
|
/// player is placed at the far-right cell via a second char where room allows;
|
|
|
|
|
|
/// callers that need the player elsewhere build the map directly.
|
2026-07-10 23:16:28 -05:00
|
|
|
|
fn map_3x1_object(grid_str: &str, ch: &str, extra: &str) -> String {
|
2026-06-15 23:35:18 -05:00
|
|
|
|
let body = if extra.is_empty() {
|
|
|
|
|
|
"kind = \"object\", tile = 64, fg = \"#00FFFF\", bg = \"#000000\"".to_string()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
format!("kind = \"object\", tile = 64, fg = \"#00FFFF\", bg = \"#000000\", {extra}")
|
|
|
|
|
|
};
|
|
|
|
|
|
map(
|
|
|
|
|
|
3,
|
|
|
|
|
|
1,
|
2026-07-10 23:16:28 -05:00
|
|
|
|
&grid(
|
|
|
|
|
|
grid_str,
|
2026-06-15 23:35:18 -05:00
|
|
|
|
&[
|
|
|
|
|
|
(" ", "kind = \"empty\""),
|
|
|
|
|
|
(".", "kind = \"empty\""),
|
|
|
|
|
|
(
|
|
|
|
|
|
"#",
|
|
|
|
|
|
"kind = \"wall\", tile = 35, fg = \"#808080\", bg = \"#606060\"",
|
|
|
|
|
|
),
|
|
|
|
|
|
("@", "kind = \"player\""),
|
|
|
|
|
|
(ch, &body),
|
|
|
|
|
|
],
|
2026-07-10 23:16:28 -05:00
|
|
|
|
),
|
2026-06-07 00:46:38 -05:00
|
|
|
|
)
|
|
|
|
|
|
}
|