# Battlemap Notation Schema (BMS) - Technical Specification ## Schema Version: 1.0 ## Complete Field Reference ### 1. Header Section (Required) | Field | Type | Description | Example | |-------|------|-------------|---------| | `BMS Version` | String | Schema version | `"1.0"` | | `Map Name` | String | Map title | `"Goblin Warrens"` | | `Grid Size` | String | Width×Height in squares | `"40x30"` | | `Grid Unit` | String | Feet per square | `"5ft"` | | `Style` | String | Visual theme | `"Stone Cavern"` | | `Lighting` | String | Ambient light | `"Dim (torchlight)"` | | `Ambient Sound` | String | Background audio | `"Dripping water"` | | `Temperature` | String | Environmental temp | `"55°F, damp"` | ### 2. Coordinate System ``` (0,0)───────→ x (width) │ │ ↓ y (height) Example: (5,10) = column 6, row 11 (5ft squares) Range: (x1,y1)-(x2,y2) defines rectangle ``` ### 3. Room Definition ```yaml ROOMS: - R1: [Room Name] (x1,y1)-(x2,y2) Walls: [Material-Thickness-Style] Floor: [Material-Texture] Ceiling: [Height-Features] Lighting: [Light sources within] Features: [Special characteristics] ``` **Wall Types:** - `Stone-1ft-Rough` - `Wood-6in-Carved` - `Iron-2ft-Reinforced` - `Masonry-1ft-Smooth` - `Natural-Rockface` **Floor Types:** - `Rough stone, debris` - `Packed earth` - `Wooden planks` - `Flagstones` - `Mosaic tile` ### 4. Door Definition ```yaml DOORS: - D1: [Door Name] Type: [Material-Single/Double-Style] Position: (x1,y1)-(x2,y2) Connects: [Room1] <-> [Room2] State: [Open/Closed]-[Locked/Unlocked] Hinges: [Side] DC: [Difficulty if locked/trapped] ``` **Door Types:** - `Wood-Single-Banded` - `Iron-Double-Portcullis` - `Stone-Sliding-Secret` - `Wood-Double-Ornate` **States:** - `Open-Unlocked` - `Closed-Locked` (DC15) - `Closed-Barred` - `Destroyed` ### 5. Object Definition ```yaml OBJECTS: - O1: [Object Name] Type: [Material-Type-Style] Position: (x1,y1)-(x2,y2) Elevation: [+/- ft from floor] State: [Condition] Contents: [What's inside] Lock: [Lock details if applicable] Trapped: [Trap details if applicable] ``` **Object Types:** - `Wood-Table-Rough` - `Stone-Throne-Ornate` - `Iron-Chest-Large` - `Wood-Barrel-Sturdy` - `Stone-Altar-Carved` ### 6. Hazard Definition ```yaml HAZARDS: - H1: [Hazard Name] Type: [Mechanical/Magical/Environmental]-[Effect] Position: (x1,y1)-(x2,y2) Trigger: [Activation mechanism] DC: [Perception/Disable DCs] Save: [Saving throw type & DC] Damage: [Damage dice] Effect: [Additional effects] Reset: [Manual/Automatic] ``` **Hazard Types:** - `Mechanical-Pit-20ft` - `Magical-Glyph-Fire` - `Environmental-Gas-Poison` - `Mechanical-Dart-Pressure` - `Magical-Fear-Aura` ### 7. Lighting Definition ```yaml LIGHTING: - L1: [Light Name] Type: [Source-Type] Position: (x,y) Radius: [Bright ft, Dim ft] Color: [Light color] Fuel: [Duration/Fuel source] Special: [Flickering/Steady etc] ``` **Light Types:** - `Torch-Wall` - `Lantern-Hanging` - `Candle-Table` - `Magical-Everburning` - `Fungi-Bioluminescent` ### 8. Connection Graph ```yaml CONNECTIONS: [Room1] -- [Door/Passage] --> [Room2] [Room2] -- [Tunnel] --> [Room3] [Room3] -- [Secret] --> [Room4] ``` **Connection Types:** - `-- [Door] -->` (Standard door) - `-- [Secret] -->` (Hidden passage) - `-- [Tunnel] -->` (Long corridor) - `-- [Stairs] -->` (Vertical connection) ### 9. Annotation Definition ```yaml ANNOTATIONS: - "[Text]" at (x,y) - "[Label]" pointing to (x1,y1)-(x2,y2) - "DM: [Note]" at (x,y) ``` ## Advanced Features ### Multi-level Maps ```yaml ELEVATION: - Base Level: 0ft - Upper Balcony: +15ft - Lower Pit: -20ft STAIRS: - S1: Spiral Stairs Position: (25,15)-(27,17) Connects: Level1 -> Level2 (+10ft) Steps: 20 ``` ### Secret/Concealed Features ```yaml SECRETS: - S1: Hidden Door Position: (14,12)-(14,14) Type: Stone-Sliding DC: 20 Perception Mechanism: Lever at (12,18) Revealed: When mechanism activated ``` ### Environmental Zones ```yaml ZONES: - Z1: Fog Bank Position: (10,10)-(20,20) Effect: Heavily obscured Save: None Movement: Normal - Z2: Slippery Ice Position: (30,30)-(40,40) Effect: Difficult terrain Save: DC 10 Acrobatics or fall prone ``` ## Visualization Standards ### Color Coding (Suggested) - **Walls:** Dark gray (#333333) - **Doors:** Brown (#8B4513) - **Hazards:** Red (#FF0000) with pattern - **Objects:** Medium gray (#666666) - **Light sources:** Yellow glow (#FFFF00) - **Water:** Blue (#0000FF) - **Difficult terrain:** Green diagonal lines - **Elevation changes:** Contour lines ### Icon Standards - **Door:** Rectangle with arc - **Chest:** Rectangle with curved lid - **Table:** Rectangle - **Chair/T hrone:** Square with back - **Torch:** Small circle with flame above - **Pit:** Diagonal hatch pattern - **Secret:** Dotted outline ## Example: Simple Guard Room ```yaml BMS Version: 1.0 Map Name: Guard Room Grid Size: 20x15 Grid Unit: 5ft Style: Stone Fortress Lighting: Torchlight ROOMS: - R1: Guard Room (0,0)-(20,15) Walls: Stone-1ft-Smooth Floor: Flagstones Ceiling: 15ft, wooden beams Lighting: Wall torches at (3,0), (17,0) DOORS: - D1: Wooden Door (20,6)-(20,9) Type: Wood-Single-Reinforced Connects: R1 -> Corridor State: Closed-Unlocked Hinges: East side OBJECTS: - O1: Guard Table (5,5)-(9,9) Type: Wood-Table-Sturdy Contents: Maps, mugs, dice - O2: Weapon Rack (15,5)-(17,10) Type: Wood-Rack-Wall Contents: 4 spears, 2 swords LIGHTING: - L1: Wall Torch (3,0) Radius: 20ft bright, 40ft dim Color: Orange flickering - L2: Wall Torch (17,0) Radius: 20ft bright, 40ft dim Color: Orange flickering ANNOTATIONS: - "Guard post" at (10,7) - "Weapons" pointing to O2 ``` ## TypeScript Interface Definition ```typescript // Core BMS Types type Coordinate = [number, number]; // (x, y) type Rectangle = { from: Coordinate; to: Coordinate }; interface BMSHeader { bmsVersion: string; mapName: string; gridSize: { width: number; height: number }; gridUnit: string; style: string; lighting: string; ambientSound?: string; temperature?: string; } interface Room { id: string; // "R1" name: string; position: Rectangle; walls: string; // "Stone-1ft-Rough" floor: string; // "Rough stone, debris" ceiling: string; // "15ft, wooden beams" lighting?: string; features?: string; } interface Door { id: string; // "D1" name: string; type: string; // "Wood-Single-Banded" position: Rectangle; connects: { room1: string; room2: string }; state: { open: boolean; locked: boolean; dc?: number }; hinges?: string; // "East side" } interface MapObject { id: string; // "O1" name: string; type: string; // "Wood-Table-Rough" position: Rectangle; elevation?: string; // "+2ft" state?: string; contents?: string; lock?: string; trapped?: string; } interface Hazard { id: string; // "H1" name: string; type: string; // "Mechanical-Pit-20ft" position: Rectangle; trigger?: string; dc?: { perception?: number; disable?: number }; save?: { type: string; dc: number }; damage?: string; effect?: string; reset?: string; } interface LightSource { id: string; // "L1" name: string; type: string; // "Torch-Wall" position: Coordinate; radius: { bright: number; dim: number }; color?: string; fuel?: string; special?: string; } interface Connection { from: string; // Room ID to: string; // Room ID type: string; // "Door", "Secret", "Tunnel", "Stairs" via?: string; // Door ID if applicable } interface Annotation { text: string; position: Coordinate; type?: "label" | "note" | "pointer"; target?: Rectangle; // For pointer annotations } interface BMSSchema extends BMSHeader { rooms?: Room[]; doors?: Door[]; objects?: MapObject[]; hazards?: Hazard[]; lightingSources?: LightSource[]; connections?: Connection[]; annotations?: Annotation[]; // Advanced features (future) elevation?: Elevation[]; stairs?: Stairs[]; secrets?: Secret[]; zones?: Zone[]; } ``` ## Parser Functions ### Grid Size Parser ```typescript function parseGridSize(str: string): { width: number; height: number } { // "40x30" → { width: 40, height: 30 } const match = str.match(/^(\d+)x(\d+)$/); if (!match) throw new Error(`Invalid grid size: ${str}`); return { width: parseInt(match[1]), height: parseInt(match[2]) }; } ``` ### Coordinate Parser ```typescript function parseCoordinate(str: string): Coordinate { // "(5,10)" → [5, 10] const match = str.match(/^\((\d+),(\d+)\)$/); if (!match) throw new Error(`Invalid coordinate: ${str}`); return [parseInt(match[1]), parseInt(match[2])]; } ``` ### Rectangle Parser ```typescript function parseRectangle(str: string): Rectangle { // "(0,0)-(20,15)" → { from: [0,0], to: [20,15] } const match = str.match(/^\((\d+),(\d+)\)-\((\d+),(\d+)\)$/); if (!match) throw new Error(`Invalid rectangle: ${str}`); return { from: [parseInt(match[1]), parseInt(match[2])], to: [parseInt(match[3]), parseInt(match[4])] }; } ``` ### Door State Parser ```typescript function parseDoorState(str: string): { open: boolean; locked: boolean; dc?: number } { // "Open-Unlocked" → { open: true, locked: false } // "Closed-Locked (DC15)" → { open: false, locked: true, dc: 15 } const match = str.match(/^(Open|Closed)-(Unlocked|Locked)(?: \(DC(\d+)\))?$/); if (!match) throw new Error(`Invalid door state: ${str}`); return { open: match[1] === "Open", locked: match[2] === "Locked", dc: match[3] ? parseInt(match[3]) : undefined }; } ``` ## Validation Rules ### Required Fields 1. `BMS Version` must be "1.0" 2. `Map Name` must be non-empty string 3. `Grid Size` must match pattern "WxH" where W,H > 0 4. `Grid Unit` must contain "ft" (e.g., "5ft") ### Coordinate Validation 1. Coordinates must be within grid bounds 2. Rectangle `from` coordinates must be ≤ `to` coordinates 3. Room rectangles must not overlap (optional warning) ### Door Validation 1. Door must connect two existing rooms 2. Door position must be on room boundary 3. Hinge side must be consistent with door position ### Lighting Validation 1. Light position must be within a room 2. Bright radius ≤ dim radius 3. Color must be valid CSS color ## Best Practices 1. **Start Simple**: Define rooms and connections first 2. **Be Specific**: Use exact coordinates, not "center of room" 3. **Consistent Naming**: R1, D1, O1, H1, L1, etc. 4. **Include DCs**: For all interactive elements 5. **Visual Notes**: Describe what players SEE 6. **Mechanical Notes**: Describe what players INTERACT WITH 7. **Layer Complexity**: Add hazards/objects after base layout --- *Last Updated: March 19, 2026*