Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>MGSL – Multi Grid Scripting LanguageNew to Visual Studio Code? Get it now.
MGSL – Multi Grid Scripting Language

MGSL – Multi Grid Scripting Language

Bojan Endrovski

|
7 installs
| (0) | Free
Syntax highlighting, diagnostics, tag-value coloring, hover, go-to-definition, and completion for .mgsl files
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

MGSL – Multi Grid Scripting Language

VS Code support for MGSL, a domain-specific language for procedural grid-based level generation. MGSL programs describe how to transform a stack of correlated grids through pattern-rewrite rules.

Features

Real-time diagnostics

Errors appear as you type — undeclared grids, unknown tag values, shape mismatches, duplicate declarations, and more.

Diagnostics

Tag value coloring

Every tag value gets a stable background color. Pattern bodies light up to show which cells carry which values — the same color you see in the tag declaration appears wherever that value is used.

Tag coloring

Colors automatically adapt to light and dark themes.

Hover information

Hover over any tag value, rule name, or grid name to see its declaration inline — including the full tagset, rule attributes, and pair count.

Go to definition

F12 (or Ctrl+click) on a tag value, rule name, or grid reference jumps to where it is declared.

Completion in pattern bodies

Inside [ … ] pattern cells, Ctrl+Space (or type [ to trigger automatically) offers all tag values declared for that grid, plus the wildcards * and ..

Syntax highlighting

Keywords, pattern wildcards (* and .), comments, and numeric literals are highlighted via a TextMate grammar.

Language quick reference

tag terrain { wall, floor }

layers {
    level: grid of terrain
}

rule fill(symmetry=all) {
    level[.]
    =>
    level[floor]
}

program {
    resize(60, 40)
    all fill
    trim()
}
Token Meaning in pattern
* match any value (including empty)
. match or write the empty cell
name a specific tag value
integer a numeric value (grid of number)
( … ) a parenthesized expression (§5.8) — e.g. (n + 1), (tiles > 5), (if(difficulty > 3, wall, floor))

Guards and runtime inputs:

tag terrain { water, grass, rock, blocker = rock | water }   // named union

params {
    difficulty: number = 3      // input param with a (mandatory) default
    budget = difficulty * 3     // derived param, computed once at startup
}

rule flood {
    { all
      map[.]
      where[ (random(1, 100) <= difficulty) ]  // per-cell guard, may use random()
    }
    => map[water]
}

program {
    resize(40, 30)
    all flood
    all place_bosses  when (budget > 6)         // statement runs only if true
}

Getting started

  1. Create a file with the .mgsl extension
  2. Declare tags and layers
  3. Write rules and a program block
  4. Diagnostics appear in the Problems panel as you edit

Resources

  • Language specification (includes the grammar reference)
  • Example scripts
  • Issues

Changelog

0.6.4

  • Synced to language v0.6.4 — the write side is now recursive: { all } / { any } blocks may nest to any depth (independent per-layer choice, correlated combos). Match side unchanged
  • Recursive shape-checking through the whole write tree, and a new check for a same-grid simultaneous write inside { all } ({ all g[wall] g[floor] }); weights still rejected in { all } at any depth

0.6.3

  • Synced to language v0.6.3 — two new program statements:
    • mirror(horizontal | vertical) — fold the grid across its centre axis; the axis is validated
    • pad(N) — add a uniform empty border on all sides; a negative margin is reported
  • New keywords mirror / pad highlighted
  • (v0.6.2 needed no extension change — it only altered symmetry=all variant expansion, a runtime/compile concern the extension doesn't model.)

0.6.1

  • Synced to language v0.6.1 — the . empty literal is now usable inside expressions: (g == .) (is-empty), (g != .) (is-non-empty), if(cond, floor, .) (conditional clear). It's polymorphic (typed from context); an untyped . (e.g. (. == .)) is reported
  • The structural cells . (empty) and * (any/preserve) are now colored in patterns — each gets its own neutral, so the most frequent pattern characters read at a glance
  • Also implemented bare tag-mask literals !tag (match-side complement, F1) and a|b (union) in pattern cells, now that examples use them

0.6.0

  • Synced to language v0.6 (execution-model rework). Strategies now separate a count (one/all/some) from an execution policy:
    • all(policy=stabilize) smooth, some(max=200, policy=incremental) walk, one(policy=ranked) collapse, some(percent=50) carve
    • Validated: unknown policy, percent with a non-snapshot policy, one with policy=stabilize, max/percent misuse
  • first body-level sub-rule combinator ({ first … }) — first matching sub-rule wins per anchor; flagged if used on a match/write side
  • New keywords highlighted: first, policy, percent, snapshot, incremental, stabilize, ranked

0.5.3

(Synced to language v0.5.3.1 — the Marketplace uses 3-part semver, so this covers v0.5.2 through v0.5.3.1.)

  • Named tag unions (v0.5.2) — blocker = wall | door inside a tag block; a union resolves as a mask anywhere a tag value can, and is validated (unknown/forward-referenced members, redeclaration, reserved/built-in collisions)
  • Param defaults (v0.5.3) — difficulty: number = 3; the default expression follows the derived-param discipline (earlier params only, no grids/positions, numeric)
  • Mandatory defaults (v0.5.3.1) — a bare name: number input is now reported as an error (every input must carry a default)

0.5.1

  • Synced to language v0.5.1.
    • when (expr) statement guards — a boolean, params-only guard on any program statement (all place when (difficulty > 3)); flagged if it reads a grid, x/y, or width/height, or is non-boolean
    • Derived params — name = expr in the params block, computed from input params and earlier-declared derived params; forward references, grid/position reads, and non-numeric results are reported
    • random(lo, hi) built-in, usable anywhere expressions are (also reserved as a name)

0.4.0

  • Synced to language v0.4. Built-in functions in expressions: if(c, a, b), min, max, abs, clamp — with full type-checking (arity, argument kinds, and if's same-type branches / boolean condition)
  • The names if, min, max, abs, clamp are reported as errors when used as a tag value, grid, or param
  • A built-in name not followed by ( is flagged as an unresolved identifier
  • Built-in calls are highlighted as functions

0.3.0

  • Synced to language v0.3.1. The extension now understands:
    • Numeric expressions in pattern cells — n[ (n + 1) ] (full §5.8 grammar: arithmetic, comparison, logical, tag-union)
    • The params { … } block for runtime numeric inputs
    • The where[ (…) ] pseudo-layer for boolean position/value guards
    • Numeric and set rotation attributes — rotation=180, rotation={90, 270}
  • Spec §7.3 checks: pattern dimension-mismatch (#3), duplicate layers/program and a missing program block (#9)
  • Expression type-checking with precise diagnostics (arithmetic/relational/logical/tag-union operand rules, identifier resolution)
  • Parser errors now name tokens by their literal spelling ('}' instead of 'RBrace')

0.2.1

  • Synced to language v0.2: dropped Unicode glyph aliases (names only)
  • Pattern wildcards swapped — * now matches any value, . is the empty cell (? is freed)
  • New trim() program statement (crops to the bounding box of non-empty content)

0.2.0

  • Hover information for tag values, rule names, and grid references
  • Go to definition (F12 / Ctrl+click)
  • Completion inside pattern bodies — tag values and wildcards
  • Coloring scoped to actual tag value references (no false positives on rule/layer names)
  • Error squiggles now land on the correct token (rule name, tag name, etc.)
  • Additional sema checks: inconsistent row widths

0.1.0

  • Initial release: syntax highlighting, real-time diagnostics, tag-value coloring
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft