mod fill_sparse; mod grid_errors; mod object_placement; mod player_placement; mod portal_placement; mod pushers; mod round_trip; mod spinners; mod transporters; 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") } /// Builds the `[grid]` block: a triple-quoted `content` grid plus an inline /// `palette` table. Each palette entry is `(char_key, inline-body)` where the /// body is the inside of the entry's `{ ... }` (e.g. `kind = "wall"`). fn grid(content: &str, palette: &[(&str, &str)]) -> String { let pal = palette .iter() .map(|(k, body)| format!("\"{k}\" = {{ {body} }}")) .collect::>() .join(", "); format!("\n[grid]\ncontent = \"\"\"\n{content}\n\"\"\"\npalette = {{ {pal} }}\n") } /// 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}") } /// 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. fn map_3x1_object(grid_str: &str, ch: &str, extra: &str) -> String { 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, &grid( grid_str, &[ (" ", "kind = \"empty\""), (".", "kind = \"empty\""), ( "#", "kind = \"wall\", tile = 35, fg = \"#808080\", bg = \"#606060\"", ), ("@", "kind = \"player\""), (ch, &body), ], ), ) }