Reference Verse compiles

Enum Branching in Verse: Coastal Zone Logic

Your island has four distinct coastal zones — Dock, Shore, Cove, and Clifftop — and each one should behave differently when a player arrives: different scores, different cinematics, different teleport destinations. Verse `enum` types give you a clean, compile-safe way to represent those zones and branch on them without a tangle of `if/else` chains. This article teaches enum declaration, enumerator access, and exhaustive branching through a real, running island scenario.

Updated Examples verified on the live UEFN compiler
Watch the Knotenum_branching in ~90 seconds.

Overview

An enum (enumeration) in Verse is a type whose only legal values are the named constants you declare inside it. Instead of tracking a zone as a raw integer or a string, you declare coastal_zone := enum { Dock, Shore, Cove, Clifftop } and the compiler guarantees every branch is reachable and every value is valid. This is the right tool whenever your game has a fixed set of mutually exclusive states — spawn regions, round phases, weapon tiers, or, as here, named coastal zones on a cel-shaded island.

Enum branching pairs with Verse's if / else if chain (or a future case expression) to dispatch different device calls — scoring, cinematics, teleportation — based on which zone a player occupies. Because the compiler knows every enumerator, you get a hard error if you typo a name, and a clear warning if you forget a branch.

API Reference

(API surface could not be resolved for this device.)

Walkthrough

Scenario

A sun-drenched cel-shaded island has four coastal zones. Each zone has a pressure plate (modelled here as a player_spawner_device firing SpawnedEvent — swap for a trigger in your own project). When a player "arrives" at a zone the manager:

  1. Reads which coastal_zone enum value that spawner represents.
  2. Awards a different point value via score_manager_device.
  3. Plays a short zone-flavour cinematic via cinematic_sequence_device.
  4. Optionally teleports the player onward via teleporter_device.

Every branch is driven by enum comparison — no magic numbers, no string comparisons.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/UI }

# ── Enum: the four coastal zones ──────────────────────────────────────────────
coastal_zone := enum:
    Dock
    Shore
    Cove
    Clifftop

# ── Device ────────────────────────────────────────────────────────────────────
coastal_zone_manager := class(creative_device):

    # One spawner per zone — assign in the UEFN editor
    @editable DockSpawner     : player_spawner_device = player_spawner_device{}
    @editable ShoreSpawner    : player_spawner_device = player_spawner_device{}
    @editable CoveSpawner     : player_spawner_device = player_spawner_device{}
    @editable ClifftopSpawner : player_spawner_device = player_spawner_device{}

    # Shared score manager — configure point value per zone in Verse
    @editable ScoreManager : score_manager_device = score_manager_device{}

    # One cinematic per zone
    @editable DockCinematic     : cinematic_sequence_device = cinematic_sequence_device{}
    @editable ShoreCinematic    : cinematic_sequence_device = cinematic_sequence_device{}
    @editable CoveCinematic     : cinematic_sequence_device = cinematic_sequence_device{}
    @editable ClifftopCinematic : cinematic_sequence_device = cinematic_sequence_device{}

    # Teleporter that sends players from Clifftop back to Dock (loop)
    @editable ClifftopTeleporter : teleporter_device = teleporter_device{}

    OnBegin<override>()<suspends> : void =
        # Subscribe each spawner to the same handler, tagging the zone
        DockSpawner.SpawnedEvent.Subscribe(OnDockArrival)
        ShoreSpawner.SpawnedEvent.Subscribe(OnShoreArrival)
        CoveSpawner.SpawnedEvent.Subscribe(OnCoveArrival)
        ClifftopSpawner.SpawnedEvent.Subscribe(OnClifftopArrival)

    # ── Arrival shims: convert spawner event → zone enum ──────────────────────
    OnDockArrival(Agent : agent) : void =
        HandleZoneArrival(Agent, coastal_zone.Dock)

    OnShoreArrival(Agent : agent) : void =
        HandleZoneArrival(Agent, coastal_zone.Shore)

    OnCoveArrival(Agent : agent) : void =
        HandleZoneArrival(Agent, coastal_zone.Cove)

    OnClifftopArrival(Agent : agent) : void =
        HandleZoneArrival(Agent, coastal_zone.Clifftop)

    # ── Core enum-branching logic ──────────────────────────────────────────────
    HandleZoneArrival(Agent : agent, Zone : coastal_zone) : void =
        # Branch on the enum value — each arm calls DIFFERENT device APIs
        if (Zone = coastal_zone.Dock):
            # Dock: baseline score, play dock cinematic
            ScoreManager.Activate(Agent)          # awards configured base points
            DockCinematic.Play(Agent)
        else if (Zone = coastal_zone.Shore):
            # Shore: one bonus increment then score
            ScoreManager.Increment(Agent)
            ScoreManager.Activate(Agent)
            ShoreCinematic.Play(Agent)
        else if (Zone = coastal_zone.Cove):
            # Cove: two increments for hidden-cove bonus
            ScoreManager.Increment(Agent)
            ScoreManager.Increment(Agent)
            ScoreManager.Activate(Agent)
            CoveCinematic.Play(Agent)
        else if (Zone = coastal_zone.Clifftop):
            # Clifftop: maximum bonus, cinematic, then loop player back to Dock
            ScoreManager.Increment(Agent)
            ScoreManager.Increment(Agent)
            ScoreManager.Increment(Agent)
            ScoreManager.Activate(Agent)
            ClifftopCinematic.Play(Agent)
            # Teleport back to the start of the coastal loop
            if (Player := player[Agent]):
                ClifftopTeleporter.Activate(Agent)

Line-by-line explanation

Lines What's happening
coastal_zone := enum: Declares the enum type. The compiler now knows exactly four legal values.
@editable DockSpawner … Each device field is wired in the UEFN editor — no bare device calls.
DockSpawner.SpawnedEvent.Subscribe(OnDockArrival) Subscribes a class-scope method to the spawner's SpawnedEvent.
HandleZoneArrival(Agent, coastal_zone.Dock) The shim converts the raw event into a typed enum value before dispatching.
if (Zone = coastal_zone.Dock): Verse equality check against an enumerator. Typo → compile error, not a silent runtime miss.
ScoreManager.Increment(Agent) Stacked increments before Activate raise the awarded points for rarer zones.
ScoreManager.Activate(Agent) Actually grants the accumulated points to the player.
ClifftopCinematic.Play(Agent) Plays the zone-specific cinematic for this player only.
ClifftopTeleporter.Activate(Agent) Teleports the player, completing the coastal loop.

Common patterns

Pattern 1 — Enum as persistent round phase, driving timer start/stop

Store the current phase in a variable and branch on it when a player interacts, using timer_device to enforce time limits per phase.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/UI }

round_phase := enum:
    Exploration
    Combat
    Escape

phase_timer_manager := class(creative_device):

    @editable PhaseTimer     : timer_device           = timer_device{}
    @editable ZoneSequence   : cinematic_sequence_device = cinematic_sequence_device{}
    @editable EscapeTeleport : teleporter_device       = teleporter_device{}

    var CurrentPhase : round_phase = round_phase.Exploration

    OnBegin<override>()<suspends> : void =
        PhaseTimer.SuccessEvent.Subscribe(OnTimerSuccess)
        # Start the first phase
        AdvancePhase()

    OnTimerSuccess(MaybeAgent : ?agent) : void =
        AdvancePhase()

    AdvancePhase() : void =
        # Branch on current phase to decide what comes next
        if (CurrentPhase = round_phase.Exploration):
            set CurrentPhase = round_phase.Combat
            PhaseTimer.Reset()
            PhaseTimer.Start()
            ZoneSequence.Play()          # fanfare cinematic for combat start
        else if (CurrentPhase = round_phase.Combat):
            set CurrentPhase = round_phase.Escape
            PhaseTimer.Reset()
            PhaseTimer.Start()
        else if (CurrentPhase = round_phase.Escape):
            # Escape phase ended — stop the timer, play outro
            PhaseTimer.Stop()
            ZoneSequence.GoToEndAndStop()

    # Minimal required override
    OnTimerStart() : void = {}

Pattern 2 — Enum controlling which cinematic plays for a player reference device event

The player_reference_device fires ActivatedEvent when a tracked player triggers it. Branch on a stored enum to pick the right cinematic.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/UI }

zone_mood := enum:
    Calm
    Tense
    Triumphant

cinematic_switcher := class(creative_device):

    @editable PlayerRef        : player_reference_device    = player_reference_device{}
    @editable CalmCinematic    : cinematic_sequence_device  = cinematic_sequence_device{}
    @editable TenseCinematic   : cinematic_sequence_device  = cinematic_sequence_device{}
    @editable TriumphCinematic : cinematic_sequence_device  = cinematic_sequence_device{}

    # Set this in the editor or via another Verse device at runtime
    var ActiveMood : zone_mood = zone_mood.Calm

    OnBegin<override>()<suspends> : void =
        PlayerRef.ActivatedEvent.Subscribe(OnPlayerActivated)

    OnPlayerActivated(Agent : agent) : void =
        # Enum branch selects the correct cinematic — no integer magic
        if (ActiveMood = zone_mood.Calm):
            CalmCinematic.Play(Agent)
        else if (ActiveMood = zone_mood.Tense):
            TenseCinematic.Play(Agent)
        else if (ActiveMood = zone_mood.Triumphant):
            TriumphCinematic.Play(Agent)

    # Call this from another device to switch mood at runtime
    SetMood(NewMood : zone_mood) : void =
        set ActiveMood = NewMood

Pattern 3 — Enum stored in a map to track per-player zone, then reset score on zone change

Demonstrates using an enum as a map value and calling score_manager_device.Reset() when the zone changes.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/UI }

coastal_sector := enum:
    OpenWater
    Reef
    Lagoon

zone_tracker := class(creative_device):

    @editable ReefSpawner      : player_spawner_device  = player_spawner_device{}
    @editable LagoonSpawner    : player_spawner_device  = player_spawner_device{}
    @editable ScoreManager     : score_manager_device   = score_manager_device{}
    @editable LagoonTeleporter : teleporter_device      = teleporter_device{}

    # Track each player's current sector
    var PlayerSectors : [agent]coastal_sector = map{}

    OnBegin<override>()<suspends> : void =
        ReefSpawner.SpawnedEvent.Subscribe(OnReefArrival)
        LagoonSpawner.SpawnedEvent.Subscribe(OnLagoonArrival)

    OnReefArrival(Agent : agent) : void =
        UpdateSector(Agent, coastal_sector.Reef)

    OnLagoonArrival(Agent : agent) : void =
        UpdateSector(Agent, coastal_sector.Lagoon)

    UpdateSector(Agent : agent, NewSector : coastal_sector) : void =
        # Look up the player's previous sector
        var PrevSector : coastal_sector = coastal_sector.OpenWater
        if (Prev := PlayerSectors[Agent]):
            set PrevSector = Prev

        # Only act if the sector actually changed
        if (PrevSector <> NewSector):
            # Reset score when leaving a zone — enum branch decides extra action
            ScoreManager.Reset(Agent)

            if (NewSector = coastal_sector.Reef):
                ScoreManager.Activate(Agent)   # small reef bonus
            else if (NewSector = coastal_sector.Lagoon):
                ScoreManager.Increment(Agent)
                ScoreManager.Activate(Agent)   # bigger lagoon bonus
                LagoonTeleporter.Activate(Agent)

            # Store updated sector — map mutation requires 'set' + 'if'
            if (set PlayerSectors[Agent] = NewSector) {}

Gotchas

1. Enumerator access uses dot notation on the type, not a bare name

# ✅ Correct
if (Zone = coastal_zone.Dock): ...

# ❌ Wrong — 'Dock' is not a standalone identifier
if (Zone = Dock): ...

Always prefix the enumerator with its type name: coastal_zone.Dock.

2. Verse has no switch/case — use if / else if chains

Verse does not yet have a case or match expression. Write exhaustive if / else if chains. The compiler does not currently warn on missing branches for enums in if chains (unlike some languages), so be disciplined about covering every enumerator.

3. Enum variables must be initialized — there is no zero-value

# ✅ Always provide an initial value
var CurrentZone : coastal_zone = coastal_zone.Dock

# ❌ Uninitialized var — compile error
var CurrentZone : coastal_zone

4. Mutable map entries require if (set Map[Key] = Value) {}

When storing an enum in a [agent]coastal_zone map, mutation is a failable expression:

if (set PlayerSectors[Agent] = NewSector) {}

Omitting the if wrapper is a compile error.

5. listenable(?agent) events need option unwrapping

Some device events (e.g. timer_device.SuccessEvent) send ?agent, not agent. Unwrap before using:

OnTimerSuccess(MaybeAgent : ?agent) : void =
    if (A := MaybeAgent?):
        ScoreManager.Activate(A)

Passing a ?agent directly to ScoreManager.Activate is a type error.

6. score_manager_device.Increment stacks — call Reset to clear

Increment raises the next award amount by 1 each call. If you forget to call Reset between rounds, the bonus accumulates across the entire session. Call ScoreManager.Reset(Agent) at round start or zone change to return to the base value.

Build your own lesson with enum_branching

Generate a personalized, step-by-step lesson plan built around this object — grounded in this exact reference and our compile-verified knowledge base.

Build a lesson →