lantern

sprout-garden-plot-types

Sprout Garden: Plot Types

The vocabulary of transformation. Each plot does ONE thing.

Core Concept

Every plot follows the same pattern:

SEED → GROW → FRUIT
  • Seed: What arrives (the input)
  • Grow: The transformation (what this plot does)
  • Fruit: What emerges (the output)

Plots differ only in:

  • Which directions they accept seeds from
  • What transformation they apply
  • Which directions they emit fruit to

Phase 1: Foundation Plots

Available from the start. Teach flow and basic transformation.

Vine (→ ↓ ← ↑)

Purpose: Carries sprout without changing it. Defines the path.

Property Value
Symbol ➡️ ⬇️ ⬅️ ⬆️
Seeds from Opposite of pointing direction + perpendiculars
Fruits to Pointing direction
Grows Pass-through (no change)
Interaction Tap to rotate 90° clockwise
{
  type: 'vine-right',
  seeds: ['left', 'up', 'down'],
  fruits: ['right'],
  grow: (sprout) => sprout,
  next: 'vine-down'  // rotation cycle
}

Teaching: Flow, direction, path planning


Form Grower (⚙️)

Purpose: Ripens the shape by one step in the cycle.

Property Value
Symbol ⚙️
Seeds from All four directions
Fruits to Pass-through (same direction it came from)
Grows shape = next in cycle

Cycle: ● circle → ■ square → ▲ triangle → ★ star → ● circle

{
  type: 'form-grower',
  seeds: ['left', 'right', 'up', 'down'],
  fruits: ['pass-through'],
  grow: (sprout) => ({
    ...sprout,
    shape: SHAPE_CYCLE[(SHAPE_CYCLE.indexOf(sprout.shape) + 1) % 4]
  })
}

Teaching: Sequential transformation, cycles, modular arithmetic


Color Bloomer (🎨)

Purpose: Blooms the color by one step in the cycle.

Property Value
Symbol 🎨
Seeds from All four directions
Fruits to Pass-through
Grows color = next in cycle

Cycle: 🔴 red → 🟢 green → 🔵 blue → 🟡 yellow → 🔴 red

{
  type: 'color-bloomer',
  seeds: ['left', 'right', 'up', 'down'],
  fruits: ['pass-through'],
  grow: (sprout) => ({
    ...sprout,
    color: COLOR_CYCLE[(COLOR_CYCLE.indexOf(sprout.color) + 1) % 4]
  })
}

Teaching: Independent transformations, multiple properties


Spring (🌱)

Purpose: Source. Emits new sprouts into the garden.

Property Value
Symbol 🌱
Seeds from None (pure source)
Fruits to All four directions (connects to adjacent vines/plots)
Grows Creates sprout from config
{
  type: 'spring',
  seeds: [],
  fruits: ['right', 'left', 'up', 'down'],
  config: {
    emits: { shape: 'circle', color: 'red' },
    mode: 'single',  // single | burst | timed | continuous
    count: 1
  }
}

Teaching: Sources, initial state


Harvest (🎯)

Purpose: Sink. Collects sprouts that arrive.

Property Value
Symbol 🎯
Seeds from All four directions
Fruits to None (terminal)
Grows Collects and validates
{
  type: 'harvest',
  seeds: ['left', 'right', 'up', 'down'],
  fruits: [],
  config: {
    expects: { shape: 'star', color: 'green' },  // null = accepts anything
    count: 1  // how many needed to complete
  }
}

Teaching: Goals, success conditions


Weeder (❌)

Purpose: Meta-plot. Removes placed plots (edit tool).

Property Value
Symbol
Not a real plot Edit action

Teaching: Iteration, experimentation


Phase 2: Imprinting Plots

Unlocked after mastering cycles. Teach direct assignment.

Form Imprinter (● ■ ▲ ★)

Purpose: Stamps a SPECIFIC shape, regardless of input.

Property Value
Symbols ●, ■, ▲, ★ (one per shape)
Seeds from All four directions
Fruits to Pass-through
Grows shape = fixed value
{
  type: 'form-imprinter-circle',
  symbol: '●',
  seeds: ['left', 'right', 'up', 'down'],
  fruits: ['pass-through'],
  grow: (sprout) => ({ ...sprout, shape: 'circle' })
}

Teaching: Assignment vs transformation, constants


Color Imprinter (🔴 🟢 🔵 🟡)

Purpose: Stamps a SPECIFIC color, regardless of input.

Property Value
Symbols 🔴, 🟢, 🔵, 🟡 (one per color)
Seeds from All four directions
Fruits to Pass-through
Grows color = fixed value

Teaching: Same as form imprinter


Phase 3: Gate Plots

Unlocked for conditional logic.

Gate (🚧)

Purpose: Only allows sprouts matching a condition to pass.

Property Value
Symbol 🚧
Seeds from All four directions
Fruits to Pass-through (if condition met)
Grows Pass if condition, otherwise block
Blocked behavior Sprout wilts (💀) or bounces back
{
  type: 'gate',
  symbol: '🚧',
  condition: { shape: 'star' },  // or { color: 'blue' } or compound
  grow: (sprout) => {
    if (matches(sprout, this.condition)) {
      return sprout;  // pass through
    }
    return null;  // blocked - sprout wilts
  }
}

Gate Variants:

  • gate-shape-circle - only circles pass
  • gate-color-red - only red passes
  • gate-fruit - only stars pass (shape = fruit stage)

Teaching: Conditionals, filtering, constraints


Phase 4: Forking Plots

Unlocked for branching logic.

Fork (⑂)

Purpose: Routes sprout to different outputs based on property.

Property Value
Symbol
Seeds from One direction (configurable)
Fruits to Two or more directions
Grows Routes based on condition
{
  type: 'fork',
  symbol: '⑂',
  seeds: ['left'],
  routing: {
    'up': { color: 'red' },      // red goes up
    'down': { color: 'blue' },   // blue goes down
    'right': 'default'           // everything else goes right
  }
}

Teaching: Pattern matching, branching, routing


Splitter (⚡)

Purpose: Duplicates sprout to ALL outputs (not conditional).

Property Value
Symbol
Seeds from One direction
Fruits to Multiple directions
Grows Clones sprout to each output
{
  type: 'splitter',
  seeds: ['left'],
  fruits: ['up', 'right', 'down'],
  grow: (sprout) => [
    { ...sprout, id: uuid() },  // clone 1
    { ...sprout, id: uuid() },  // clone 2
    { ...sprout, id: uuid() }   // clone 3
  ]
}

Teaching: One-to-many, parallel paths


Grafter (⊕)

Purpose: Combines multiple inputs into one output.

Property Value
Symbol
Seeds from Multiple directions (multiple seed slots)
Fruits to One direction
Grows Waits for all seeds, then combines
{
  type: 'grafter',
  seeds: ['left', 'up'],  // two seed slots
  fruits: ['right'],
  grow: (seeds) => {
    if (seeds.left && seeds.up) {
      return combine(seeds.left, seeds.up);
    }
    return null;  // wait for both
  }
}

Combine modes:

  • first - output first arrived
  • merge - combine properties
  • recipe - specific combination produces specific output

Teaching: Joins, synchronization, AND logic


Phase 5: Logic Trellises

Unlocked for boolean algebra.

AND Trellis (∧)

Purpose: Outputs only if BOTH inputs present.

Same as Grafter with mode = 'both-required'.


OR Trellis (∨)

Purpose: Outputs if EITHER input present.

{
  type: 'or-trellis',
  seeds: ['left', 'up'],
  fruits: ['right'],
  grow: (seeds) => seeds.left || seeds.up  // first available
}

NOT Trellis (¬)

Purpose: Inverts property.

{
  type: 'not-trellis',
  grow: (sprout) => ({
    ...sprout,
    color: OPPOSITE_COLOR[sprout.color],  // red↔green, blue↔yellow
    shape: OPPOSITE_SHAPE[sprout.shape]   // circle↔star, square↔triangle
  })
}

XOR Trellis (⊕)

Purpose: Outputs if ONE but not BOTH inputs.


Phase 6: Timing Plots

For synchronization puzzles.

Delay (⏱️)

Purpose: Holds sprout for N ticks before releasing.

Property Value
Symbols ⏱️¹, ⏱️², ⏱️³
Seeds from All directions
Fruits to Pass-through (after delay)
Grows Holds, then releases
{
  type: 'delay-2',
  delay_ticks: 2,
  held_sprout: null,
  held_since: null,
  grow: function(sprout, current_tick) {
    if (this.held_sprout) {
      if (current_tick - this.held_since >= this.delay_ticks) {
        const result = this.held_sprout;
        this.held_sprout = null;
        return result;  // release
      }
      return null;  // still holding
    }
    this.held_sprout = sprout;
    this.held_since = current_tick;
    return null;  // start holding
  }
}

Teaching: Timing, synchronization, path length compensation


Phase 7: Loop Constructs

For iteration.

Merge (⊕)

Purpose: Entry point for loops. Accepts from outside AND from loop-back.

Check (❓)

Purpose: Condition check. Routes to exit or back to loop.

Counter (+1)

Purpose: Increments a counter property on the sprout.

{
  type: 'counter',
  grow: (sprout) => ({
    ...sprout,
    count: (sprout.count || 0) + 1
  })
}

Phase 8: Rabbit Holes

For abstraction/functions.

Rabbit Hole (🌀)

Purpose: Portal to sub-garden. Function call.

Property Value
Symbol 🌀
Seeds from One direction
Fruits to One direction
Contains Full sub-garden
{
  type: 'rabbit-hole',
  symbol: '🌀',
  seeds: ['left'],
  fruits: ['right'],
  subgarden: 'triple-ripen',  // reference to saved function
  grow: (sprout) => executeSubgarden(this.subgarden, sprout)
}

Interaction: Click to zoom into sub-garden. Edit it. Zoom back out.

Teaching: Abstraction, composition, functions, recursion


Wanderland Equivalents

Sprout Garden Plot Wanderland Fence
Vine Reflex / Arrow
Form Grower Transformer
Color Bloomer Transformer
Spring Source / Watcher
Harvest Sink / Accumulator
Gate Filter / Validator
Fork Router / Pattern Match
Grafter Join / Aggregator
Delay Buffer / Queue
Rabbit Hole Sub-graph / Function

Same semantics. Different skin.


Implementation Notes

Plot Interface

class Plot {
  constructor(type, config = {}) {
    this.type = type;
    this.config = config;
    this.seeds = {};      // { direction: sprout }
    this.fruit = null;
  }

  canReceiveSeed(fromDirection) {
    return PLOT_TYPES[this.type].seeds.includes(fromDirection);
  }

  receiveSeed(sprout, fromDirection) {
    this.seeds[fromDirection] = sprout;
  }

  hasSeed() {
    return Object.values(this.seeds).some(s => s !== null);
  }

  grow() {
    // Hot Potato: if we have seeds, process them
    const growFn = PLOT_TYPES[this.type].grow;
    this.fruit = growFn(this.seeds, this.config);
    this.seeds = {};  // consumed
  }

  getFruitDirections() {
    return PLOT_TYPES[this.type].fruits;
  }
}

Adding New Plot Types

Just add to the registry:

PLOT_TYPES['my-new-plot'] = {
  symbol: '🆕',
  seeds: ['left', 'right'],
  fruits: ['up'],
  grow: (seeds) => transform(seeds)
};

The engine doesn't change. Just the vocabulary.


Tags

sprout-garden, plot-types, fences, transformations, game-mechanics

Slots

North

slots:
- sprout-garden

South

slots: []

East

slots: []

West

slots: []