bms-forge/docs/BMS_SCHEMA_SPEC.md
2026-03-19 01:09:12 -04:00

10 KiB
Raw Blame History

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

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

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

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

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

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

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

ANNOTATIONS:
- "[Text]" at (x,y)
- "[Label]" pointing to (x1,y1)-(x2,y2)
- "DM: [Note]" at (x,y)

Advanced Features

Multi-level Maps

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

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

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

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

// 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

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

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

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

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