← Back to path Download .md

🐻 North Jungle

Teen 37 lessons Β· ~296 min Β· Generated 2026-07-04

Real UEFN island for Codewood Grove: dense jungle terrain with an elevated rally circuit connecting the pin landmarks β€” starting grid clearing (Palm Grove), cliff climb (Clifftop Lookout), rope-bridge canyon crossing with a physics-free swinging gate prop (creative_prop animated

Learning Outcomes

Lesson 1: Nouns of Verse: Values and Types

Objectives

Read and declare int/float/string/logic values and understand every type used in the rally code.

🧩 Your capstone piece: Core literacy for every Jungle Mod-Rally script

Quiz

  1. Why does the lesson say `90` and `90.0` are different even though both mean 'ninety' to us?
    • A. 90.0 is rounded and 90 is exact
    • B. 90 is an int (whole number) and 90.0 is a float (has a decimal part) -- they are different types
    • C. 90.0 can change during play but 90 cannot
    • D. 90.0 is text and 90 is a number
  2. You want to track each player's score so you can hand in a player and get back their score. Which container type does the lesson recommend?
    • A. An array `[]int`, since scores are a list of numbers
    • B. An option `?int`, since a score might not be there
    • C. A map `[agent]int`, which pairs each player (key) with their score (value)
    • D. A struct holding agent and int together
  3. After writing `var CurrentScore : int = 0`, why must you write `set CurrentScore = CurrentScore + 1` rather than just `CurrentScore = CurrentScore + 1`?
    • A. Because `set` is required to change a variable -- Verse makes changing state a deliberate, spelled-out act
    • B. Because `set` converts the int to a float first
    • C. Because without `set` the new value would be a constant
    • D. Because `set` is only needed inside functions, not elsewhere
  4. The lesson declares `var WinnerName : ?string = false`. What does the `?` in front of the type mean, and why does it start as `false`?
    • A. It means the string is optional to type; false means it's blank
    • B. It marks an option -- a value that might be there or not -- and `false` means 'nothing yet' (nobody's won)
    • C. It means the value is uncertain and Verse will guess it
    • D. It makes WinnerName a logic value that is currently false
  5. The lesson declares `StormPhase : int = 1` with no `var`. Later you write `set StormPhase = 2`. What happens?
    • A. It works -- `set` can change any noun
    • B. It fails -- without `var`, StormPhase is a constant, decided once and locked for the whole match
    • C. It works, but only inside a device
    • D. It silently keeps the old value of 1
Answer key
  1. B β€” The lesson points out the `.0` matters: `90` is an `int` and `90.0` is a `float` -- different types, like '3 chests' versus '3.0 chests.' A noun's type determines what values it can hold.
  2. C β€” The lesson describes a map `[k]v` as a lookup table -- exactly a leaderboard mapping each agent to an int. Hand it a player, it hands back their score. An array is ordered but not keyed by player.
  3. A β€” The lesson says you can't quietly reassign a variable; the `set` keyword is the deliberate signal -- to you and the reader -- that the game's state just moved.
  4. B β€” The lesson explains `?type` is an option: maybe-there, maybe-not, like a chest that might be empty. Starting at `false` means 'no result yet,' and the `?` forces you to check before using it.
  5. B β€” No `var` means constant. The lesson's rule: a constant is decided once and never changes during the game, like a wall's color set in the editor. Only nouns declared with `var` can be changed with `set`.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Core literacy for every Jungle Mod-Rally script

Sources

Lesson 2: Variables: State That Changes Mid-Race

Objectives

Declare var vs constant, use set, and track a changing lap counter.

πŸ” Builds on: south-shores mutable var/set lesson (prerequisite recap)

🧩 Your capstone piece: Racer lap/boost counters (mutable state)

Quiz

  1. According to the lesson, what is a variable?
    • A. A named storage space that holds data which can change
    • B. A value that is set once and can never change
    • C. A device you place in your level
    • D. A signal that fires when something happens
  2. The lesson compares a constant to a statue. Why?
    • A. A constant is set once and never changes
    • B. A constant is heavier in memory than a variable
    • C. A constant can only hold stone-type values
    • D. A constant is visible to all players in the level
  3. In the line `Score: integer = 0`, what does `integer` tell Verse?
    • A. Score holds whole numbers
    • B. Score holds numbers with decimals
    • C. Score holds text strings
    • D. Score holds true/false values
  4. When the game starts and the slider has not been touched yet, what value does `Score` hold?
    • A. 0
    • B. 1
    • C. Whatever the slider is currently set to
    • D. It holds no value until the first event fires
  5. Which line in the walkthrough connects your code to the slider's "I moved!" signal?
    • A. slider.OnValueChanged().Subscribe(OnSliderChanged)
    • B. slider.GetValue()
    • C. Score = Int(new_value)
    • D. Print("Score is now: {Score}")
Answer key
  1. A β€” The lesson describes a variable as a named storage space holding a piece of data that can change β€” like a bucket of water where the amount can go up or down.
  2. A β€” A constant is like a statue: it is set once and never changes. Variables are for things that change (like scores); constants are for things that don't (like gravity strength).
  3. A β€” The lesson explains that `integer` means the variable holds whole numbers. Score is created with the name `Score`, the type `integer`, and a starting value of 0.
  4. A β€” `Score: integer = 0` starts the variable at zero. It only changes later, when the slider's OnValueChanged event fires and OnSliderChanged updates it.
  5. A β€” Subscribing to `OnValueChanged()` means you listen for the slider's event. When the slider moves, the event fires and your subscribed function `OnSliderChanged` runs.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Racer lap/boost counters (mutable state)

Sources

Lesson 3: Functions: Name Your Logic

Objectives

Write functions with parameters and return values and call them from OnBegin.

πŸ” Builds on: south-shores one-responsibility-per-function reference

🧩 Your capstone piece: FormatTime/AwardBoost helper functions

Quiz

  1. In this lesson, a Verse function is compared to what everyday thing?
    • A. A recipe β€” named steps you write once and call whenever you need them
    • B. A treasure map that only works one time
    • C. A random number generator
    • D. A save file that stores your island
  2. What does the `@editable` tag on `Trap : trap_device = trap_device{}` let you do?
    • A. Rename the trap during a live game session
    • B. Assign a real device from your island to the property in the UEFN Details Panel
    • C. Let players edit the trap's damage in-game
    • D. Automatically spawn a new trap when the game starts
  3. In the final `ButtonTrapController`, what does `Button.InteractedWithEvent.Subscribe(FireTheTrap)` do?
    • A. It fires the trap immediately, once, when the game starts
    • B. It renames the button to FireTheTrap
    • C. It tells the game to call `FireTheTrap` every time a player presses the button
    • D. It disables the button until the trap is enabled
  4. Why does the `Subscribe` call live inside `OnBegin<override>()<suspends>`?
    • A. Because Subscribe only works on traps, not buttons
    • B. Because OnBegin runs automatically when the game session starts, so the listener is set up before anyone can press the button
    • C. Because functions can only be defined inside OnBegin
    • D. Because OnBegin runs every time the button is pressed
  5. Predict the output: a player presses the button once with the final code from Step 3. What happens?
    • A. The trap enables and "Target acquired! Boom!" prints to the console
    • B. Nothing β€” the button has to be pressed twice
    • C. The trap enables silently; Print only works in OnBegin
    • D. "Boom! The trap fired!" prints but the trap stays disabled
Answer key
  1. A β€” The article explains a function like a recipe: it has a name (like "Make Pancakes") and a set of steps. You write it once and call it by name whenever you need it β€” just like `FireTheTrap`.
  2. B β€” `@editable` exposes the property in the Details Panel so you can drag your actual Trap device from the world into the `Trap` slot. Without it, the Verse device has no way to know which trap to control.
  3. C β€” `Subscribe` hooks your function up to the button's `InteractedWithEvent`. From then on, whenever a player interacts with the button, the game automatically calls `FireTheTrap` with the presser as the agent.
  4. B β€” `OnBegin` runs automatically when the game session starts. That makes it the right place to subscribe: the button's event is wired to `FireTheTrap` before any player gets a chance to press it.
  5. A β€” Pressing the button fires `InteractedWithEvent`, which calls `FireTheTrap`. That function runs `Trap.Enable()` and then `Print("Target acquired! Boom!")`, which you can see in the console (press the `~` key).

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” FormatTime/AwardBoost helper functions

Sources

Lesson 4: If/Else: Branching Race Decisions

Objectives

Write failable conditions and if/else chains that gate gameplay logic.

🧩 Your capstone piece: Checkpoint-order validation and win checks

Quiz

  1. In Verse, what does an `if` expression use to decide which branch runs?
    • A. Whether the condition succeeds or fails
    • B. Whether the condition returns a number
    • C. Random chance
    • D. The player's score
  2. How do you test a `logic` variable named `DoorIsOpen` inside an `if`?
    • A. if (DoorIsOpen == true):
    • B. if (DoorIsOpen?):
    • C. if (DoorIsOpen!):
    • D. if (DoorIsOpen = true?):
  3. Which method starts the Prop Mover moving toward its open position?
    • A. DoorMover.Open()
    • B. DoorMover.Move()
    • C. DoorMover.Begin()
    • D. DoorMover.Start()
  4. Which trigger event fires when a player walks OUT of the trigger volume?
    • A. TriggeredEvent
    • B. ExitEvent
    • C. EndTriggerEvent
    • D. LeaveEvent
  5. How do you change the value of a `var` in Verse?
    • A. DoorIsOpen = true
    • B. set DoorIsOpen = true
    • C. DoorIsOpen := true
    • D. let DoorIsOpen = true
Answer key
  1. A β€” Verse conditions are driven by success and failure rather than only a plain true/false comparison.
  2. B β€” A `logic` value is read with a trailing `?`, so `if (DoorIsOpen?):` succeeds when it is true.
  3. C β€” `Begin()` starts the prop mover; `End()` sends it back the other way.
  4. C β€” `EndTriggerEvent` fires when a player leaves the trigger; `TriggeredEvent` fires on entry.
  5. B β€” Reassigning a mutable variable always uses the `set` keyword: `set DoorIsOpen = true`.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Checkpoint-order validation and win checks

Sources

Lesson 5: Loops: Repeat Until the Finish Line

Objectives

Use for and loop/break to iterate collections and run countdowns.

🧩 Your capstone piece: 3-2-1 race countdown loop and per-racer iteration

Quiz

  1. Which Verse keyword does the disco-ball script use to repeat its spin code forever?
    • A. loop
    • B. while
    • C. repeat
    • D. forever
  2. What does `Sleep(0.05)` do inside `RunSpinLoop()`?
    • A. Pauses the loop for 0.05 seconds before the next iteration
    • B. Stops the loop permanently after 0.05 seconds
    • C. Pauses the loop for 5 seconds
    • D. Delays the game from starting for 0.05 seconds
  3. Why would removing `Sleep(0.05)` from the spin loop be a bug?
    • A. The loop would run thousands of times per second and could freeze the game
    • B. The Prop Mover would refuse to start moving
    • C. Verse would skip the loop body entirely
    • D. CurrentYaw would stop increasing
  4. Why does `OnBegin<override>()` need the `<suspends>` specifier in this script?
    • A. Because it uses `Sleep()`, which requires a function that is allowed to pause and wait
    • B. Because every Verse function must be marked `<suspends>`
    • C. Because it makes the loop run faster
    • D. Because `@editable` properties only work in suspending functions
  5. With `SpinStepDegrees` at 5.0 and `Sleep(0.05)` each tick, roughly how many degrees are added to `CurrentYaw` per second?
    • A. About 100 degrees
    • B. About 5 degrees
    • C. About 20 degrees
    • D. About 0.25 degrees
Answer key
  1. A β€” Verse uses the `loop` keyword for an infinite loop: the code inside runs top to bottom, then jumps straight back to the top and never stops on its own.
  2. A β€” `Sleep(0.05)` pauses the code for 0.05 seconds each time through the loop β€” roughly 20 ticks per second β€” which keeps the spin smooth.
  3. A β€” Without a `Sleep()` pause, an infinite `loop` runs as fast as the computer can go β€” thousands of iterations per second β€” which can freeze or crash the game.
  4. A β€” `<suspends>` tells Verse the function may pause and wait. `Sleep()` (and other timing tools) can only be called from a suspending context, so `OnBegin` and `RunSpinLoop` both carry it.
  5. A β€” 0.05 s per tick gives roughly 20 ticks per second, and each tick adds 5.0 degrees β€” so about 20 x 5 = 100 degrees per second.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” 3-2-1 race countdown loop and per-racer iteration

Sources

Lesson 6: Strings: Length, Slicing, Name Tags

Objectives

Measure and build strings to format racer name tags and HUD text.

πŸ” Builds on: south-shores string-interpolation lesson

🧩 Your capstone piece: Racer name-tag and lap-time text formatting

Quiz

  1. What does `"JosΓ©".Length` return in Verse?
    • A. 4
    • B. 5
    • C. 6
    • D. It fails to compile
  2. Which of the following correctly passes a string to `hud_message_device.Show`?
    • A. HUD.Show("Welcome!")
    • B. HUD.Show(StringToMessage("Welcome!"))
    • C. WelcomeMsg<localizes>() : message = "Welcome!" then HUD.Show(WelcomeMsg())
    • D. HUD.Show(message{"Welcome!"})
  3. What does `SetDisplayTime(0.0)` do on a `hud_message_device`?
    • A. Hides the message immediately
    • B. Displays the message for zero seconds (no visible effect)
    • C. Displays the message persistently until Hide or ClearAllMessages is called
    • D. Resets the display time to the device's default
  4. A `trigger_device.TriggeredEvent` handler must have which signature?
    • A. (Agent : agent) : void
    • B. (MaybeAgent : ?agent) : void
    • C. () : void
    • D. (Agent : player) : void
  5. You want to limit a `trigger_device` to fire exactly 5 times. Which call is correct, and what does `GetTriggerCountRemaining()` return when the limit is set to 0?
    • A. SetMaxTriggerCount(5); GetTriggerCountRemaining() returns 5 when unlimited
    • B. SetMaxTriggerCount(5); GetTriggerCountRemaining() returns 0 when unlimited
    • C. SetMaxTriggerCount(0) means 0 fires; GetTriggerCountRemaining() returns -1 when unlimited
    • D. SetMaxTriggerCount(5) is clamped to 20; GetTriggerCountRemaining() returns -1 when unlimited
Answer key
  1. B β€” Verse's `.Length` counts UTF-8 code units, not Unicode characters. The accented `Γ©` encodes as two UTF-8 code units, so the total is 5.
  2. C β€” hud_message_device.Show requires a `message` type. The only correct way is to declare a `<localizes>` function that returns `message` and call it. There is no `StringToMessage` in Verse, and string literals are not `message` values.
  3. C β€” Per the API, passing 0.0 to SetDisplayTime means the message is displayed persistently β€” it stays on screen until explicitly hidden.
  4. B β€” TriggeredEvent is typed as listenable(?agent), so the handler receives an optional agent (?agent). Using a non-optional `agent` or `player` type would be a compile error.
  5. B β€” SetMaxTriggerCount(5) correctly limits to 5 fires (clamped to [0,20]). When MaxTriggerCount is 0 (unlimited), GetTriggerCountRemaining() returns 0 β€” not a countdown, just the sentinel for 'unlimited'.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Racer name-tag and lap-time text formatting

Sources

Lesson 7: Arrays: The Checkpoint List

Objectives

Create, index (failably), and iterate arrays of devices and players.

🧩 Your capstone piece: Ordered checkpoints[] and racers[] arrays

Quiz

  1. In the GemCounterDevice, how does the article create an empty array of strings?
    • A. var Gems : list<string> = new list()
    • B. var Gems : string[] = []
    • C. var Gems : []string = empty
    • D. var Gems : []string = array{}
  2. OnBegin appends "Ruby", then "Emerald", then "Sapphire". What does the `for (Gem : Gems):` loop print FIRST?
    • A. Found a gem: Ruby
    • B. Found a gem: Gems
    • C. Found a gem: Emerald
    • D. Found a gem: Sapphire
  3. After the three appends, Gems holds Ruby, Emerald, Sapphire. Which gem does `Gems[2]` give you (inside a failure context)?
    • A. Emerald
    • B. Nothing β€” index 2 is out of bounds for 3 items
    • C. Sapphire
    • D. Ruby
  4. A learner removes `var` and writes `Gems : []string = array{}`. Why does `set Gems = Gems + array{"Ruby"}` now fail to compile?
    • A. Arrays without `var` can only hold one element
    • B. `set` only works inside GetFirstGem, not OnBegin
    • C. String arrays are always read-only in Verse
    • D. Class fields in Verse are immutable by default; without `var` you cannot reassign Gems with `set`
  5. Spot the bug: `set Gems = Gems + "Diamond"` does not compile. What is the fix the article teaches?
    • A. Use Gems.Push("Diamond") instead
    • B. Use Gems.Add("Diamond") instead
    • C. Wrap it in a for loop before appending
    • D. Concatenate a single-element array instead: set Gems = Gems + array{"Diamond"}
Answer key
  1. D β€” The lesson declares `var Gems : []string = array{}`. The `[]string` type means an array of strings, and `array{}` is the literal for an empty array.
  2. A β€” Arrays keep items in order, and appending adds to the end. "Ruby" was added first, so it sits at index 0 and the loop visits it first, printing `Found a gem: Ruby`.
  3. C β€” Indexes start at 0: Ruby is [0], Emerald is [1], Sapphire is [2]. With 3 items the last valid index is 2 (.Length - 1), so `Gems[2]` succeeds and yields "Sapphire".
  4. D β€” The lesson calls this out in the code comments: class fields are immutable by default, so `var` is required to be able to `set` (reassign) the array after appending.
  5. D β€” You append by concatenating two arrays: `Gems + array{"Diamond"}` builds a new array with the extra item at the end, and `set` stores it back into the var field. Adding a bare string to an array is a type mismatch.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Ordered checkpoints[] and racers[] arrays

Sources

Lesson 8: Sum an Array: Total Boost Score

Objectives

Accumulate over an array to compute totals like collected boosts.

🧩 Your capstone piece: Total-boosts and total-time aggregation

Quiz

  1. What is the correct way to iterate over every element in a `[]int` array called `Scores` and accumulate a sum in Verse?
    • A. for (S : Scores): set Total += S
    • B. foreach (S in Scores) { Total += S; }
    • C. Scores.ForEach(S => Total += S)
    • D. while (Scores.HasNext()): set Total += Scores.Next()
  2. You want to pass a computed string to `hud_message_device.Show()`. Which approach compiles correctly?
    • A. HUD.Show("Gold: {Total}")
    • B. HUD.Show(StringToMessage("Gold: {Total}"))
    • C. Declare `GoldMsg<localizes>(S:string):message = "{S}"` then call `HUD.Show(GoldMsg("Gold: {Total}"))`
    • D. HUD.Show(message{"Gold: {Total}"})
  3. `trigger_device.TriggeredEvent` fires with what payload type?
    • A. agent
    • B. ?agent
    • C. []agent
    • D. void
  4. What does passing `0` to `SetMaxTriggerCount` mean?
    • A. The trigger is disabled immediately.
    • B. The trigger can fire zero times (effectively off).
    • C. The trigger has no limit on how many times it can fire.
    • D. The trigger resets its count to zero.
  5. You have a `[]float` sum called `TotalDamage` and want to display it as an integer on the HUD. Which snippet is correct Verse?
    • A. HUD.Show(Msg("{TotalDamage}"))
    • B. if (T := Int[TotalDamage]): HUD.Show(Msg("{T}"))
    • C. HUD.Show(Msg("{int(TotalDamage)}"))
    • D. HUD.Show(Msg("{TotalDamage:int}"))
Answer key
  1. A β€” Verse uses `for (Element : Array):` to iterate. The mutable variable must be updated with `set Total += S`. The other options use syntax from other languages that does not exist in Verse.
  2. C β€” `message` is a distinct type from `string`. The only way to create one from a runtime string is a `<localizes>` function. `StringToMessage` does not exist in the Verse API.
  3. B β€” The API surface declares `TriggeredEvent : listenable(?agent)`. The payload is an *optional* agent because the trigger can be fired from code with no agent involved. Handlers must accept `(MaybeAgent : ?agent)` and unwrap with `if (A := MaybeAgent?)`.
  4. C β€” Per the API docs, `0` indicates **no limit** on trigger count. To make a trigger fire only once, pass `1`.
  5. B β€” Verse does not auto-convert `float` to `int`. The failable `Int[]` subscript operator converts a float to int and must be used inside a failure context such as `if`. The other options either use non-existent casts or embed a float directly where an int is expected.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Total-boosts and total-time aggregation

Sources

Lesson 9: Count Matching: How Many Racers Passed?

Objectives

Count array elements matching a condition (racers past checkpoint N).

🧩 Your capstone piece: Racers-remaining and checkpoint-progress counters

Quiz

  1. Fill in the blank. Barnaby's counter should tally racers who have completed at least 2 laps: for (Laps : RacerLaps): ______ set Count += 1 Which condition line completes it?
    • A. if (Laps >= 2):
    • B. if (Laps => 2):
    • C. for (Laps >= 2):
    • D. when (Laps >= 2):
  2. Inside the loop, which statement correctly bumps the counter when the condition passes?
    • A. set Count += 1
    • B. Count += 1
    • C. Count = Count + 1
    • D. var Count += 1
  3. What is the ONE difference between the sum-an-array pattern and the count-matching pattern?
    • A. Counting adds 1 per element that passes a condition; summing adds each element's value with no condition.
    • B. Counting needs a `loop` block; summing needs a `for` block.
    • C. Counting only works on []int arrays; summing works on any array.
    • D. Counting requires a map; summing requires an array.
  4. You want to count racers on EXACTLY lap 2 (not 2 or more). Which condition is correct Verse?
    • A. if (Laps = 2):
    • B. if (Laps == 2):
    • C. if (Laps is 2):
    • D. if (Laps equals 2):
  5. Predict the output. With the sample data `RacerCheckpoints := array{3, 1, 4, 2, 4, 0}` and `ReportCheckpoint := 3`, what does `CountAtLeast(RacerCheckpoints, ReportCheckpoint)` return?
    • A. 3
    • B. 2
    • C. 4
    • D. 11
Answer key
  1. A β€” A count-matching condition is a failable `if` around the increment: `if (Laps >= 2):`. The comparison operator is `>=` (not `=>`), and `for`/`when` are not condition guards here β€” the `for` loop already iterates the array.
  2. A β€” Mutating a `var` in Verse always requires the `set` keyword: `set Count += 1`. Without `set` the compiler rejects the mutation, and `var` only appears at declaration.
  3. A β€” Both use the same `var` + `for` skeleton. Summing accumulates the element's value (`set Total += Value`); counting wraps an `if` condition around `set Count += 1` so only matching elements are tallied.
  4. A β€” In a Verse condition, equality is checked with a single `=` β€” it is a failable comparison, not an assignment. There is no `==` operator in Verse; use `<>` for not-equal.
  5. A β€” The condition is `Value >= 3`. The values 3, 4 and 4 pass, so the counter bumps three times and `CountAtLeast` returns 3. 11 would be the SUM of the passing values β€” counting adds 1 per match, not the value.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Racers-remaining and checkpoint-progress counters

Sources

Lesson 10: Filter an Array: Still-Racing List

Objectives

Build a new array of only the elements passing a test.

🧩 Your capstone piece: still_racing := racers filtered by not-finished

Quiz

  1. In `Survivors := for (P : AllPlayers, Char := P.GetFortCharacter[], Char.GetHealth() > 50.0) { P }`, what does `Survivors` contain?
    • A. Every player in AllPlayers, unchanged
    • B. A new array of only the players who have a character and more than half health
    • C. The single player with the highest health
    • D. The original AllPlayers array with the failing players deleted from it
  2. Why can't you pass `"Welcome aboard!"` directly to `WelcomeHud.Show(Agent, ...)`?
    • A. Show only accepts integers
    • B. The parameter is typed `message`, so you need a localized value from a <localizes> helper
    • C. You must call StringToMessage first
    • D. Strings are not allowed anywhere in Verse
  3. What must be true of each clause used as a filter inside a `for` expression?
    • A. It must return void
    • B. It must be a Print statement
    • C. It must be failable (it can fail, which skips that element)
    • D. It must be an editable field
  4. What does `GetTriggerCountRemaining()` return when the trigger's max count is set to 0 (unlimited)?
    • A. 0
    • B. 20
    • C. The number of players online
    • D. It throws an error
  5. Why is the health comparison written as `Char.GetHealth() > 50.0` and not `> 50`?
    • A. Style preference only
    • B. GetHealth returns a float and Verse does not auto-convert int to float
    • C. 50.0 is faster to compute
    • D. Health is stored as a string
Answer key
  1. B β€” The failable filter clauses skip any element that fails, so the for builds a brand-new array containing only the elements that passed both tests. AllPlayers itself is unchanged.
  2. B β€” The Show overload takes a `message`, not a raw string. You build one with a `<localizes>` function like `Banner(S:string):message = "{S}"`. There is no StringToMessage.
  3. C β€” Filter clauses are failable expressions. If a clause fails for an element, that element is skipped and not added to the result array.
  4. A β€” The API states it returns 0 if the max trigger count is unlimited, so a `Remaining > 0` guard would incorrectly skip in that case.
  5. B β€” GetHealth returns a float. Verse never auto-converts between int and float, so you must compare against a float literal like 50.0.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” still_racing := racers filtered by not-finished

Sources

Lesson 11: Maps: [player]int Progress Tracking

Objectives

Store and update per-player data in [player]int maps β€” the pattern that carries progress between zones.

🧩 Your capstone piece: LapsOf:[player]int and BestTime:[player]int maps (zone-progress persistence hook)

Quiz

  1. In the declaration `PlayerScores : [Player]int = map{}`, what does `[Player]int` mean?
    • A. It is a list holding both Players and ints
    • B. It is an array of Players with int indexes
    • C. The key type is int and the value type is Player
    • D. The key type is Player and the value type is int
  2. Fill in the blank: to start the scoreboard with no scores stored yet, the lesson initializes the map with `PlayerScores : [Player]int = ____`.
    • A. new map
    • B. empty()
    • C. []
    • D. map{}
  3. A player already has 2 points stored in `PlayerScores`. They trigger `HandleHit` one more time. What does the Print line report?
    • A. That the player now has 2 points
    • B. Nothing β€” the map must be cleared first
    • C. That the player now has 3 points
    • D. That the player now has 1 point
  4. Which expression does the lesson use to LOOK UP a player's current score in the map?
    • A. PlayerScores->Attacker
    • B. PlayerScores(Attacker)
    • C. PlayerScores[Attacker]
    • D. PlayerScores.Find(Attacker)
  5. According to the lesson, why is a map faster than searching a list for a player's score?
    • A. Maps can only hold a small number of items
    • B. Maps compress the data so there is less to search
    • C. You look the value up instantly by its key instead of digging through items one by one
    • D. Maps store their items in alphabetical order
Answer key
  1. D β€” In a Verse map type, the type in square brackets is the key and the type after it is the value. `[Player]int` maps each Player (key) to an int score (value).
  2. D β€” `map{}` creates an empty map β€” like an empty shelf with no labels on it yet, ready to store key-value pairs.
  3. C β€” `HandleHit` looks up the current score (2), adds 1 to get `NewScore` (3), stores it back with `PlayerScores[Attacker] = NewScore`, then prints the new total of 3 points.
  4. C β€” Maps are read with square brackets around the key: `PlayerScores[Attacker]` hands you the value stored under that player, like reading the labeled shelf.
  5. C β€” The lesson's toy-shelf analogy: instead of digging through the whole box (a list), you go straight to the labeled shelf. A map gives you the value for a key instantly β€” no one-by-one searching.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” LapsOf:[player]int and BestTime:[player]int maps (zone-progress persistence hook)

Sources

Lesson 12: Optionals: Maybe There Is a Vehicle

Objectives

Declare ?type, unwrap with if(X := MaybeY?), and return false-y absence safely.

🧩 Your capstone piece: Safe agentβ†’fort_character and vehicle lookups

Quiz

  1. You have `var BonusLife : ?int = false`. Which line correctly gives `BonusLife` the value 5?
    • A. set BonusLife = 5
    • B. set BonusLife = option{5}
    • C. set BonusLife = ?5
    • D. set BonusLife = [5]
  2. Why must `GetFortCharacter` be called as `Player.GetFortCharacter[]` with square brackets, not `()`?
    • A. Square brackets are faster than parentheses
    • B. Its API signature is `<decides>` β€” the call can fail, and failable expressions require `[]`
    • C. It returns an array of characters
    • D. Parentheses are only for events
  3. Inside `if (Extra := BonusLife?):`, what is the type of `Extra` in the body?
    • A. ?int β€” still an option
    • B. int β€” the unwrapped value, guaranteed present
    • C. logic β€” a boolean
    • D. false β€” the empty option
  4. A field is declared `DailyGift : ?daily_gift = false`. What does the `= false` mean here?
    • A. The gift is disabled by a boolean flag
    • B. It's a typo; options can't have defaults
    • C. It initializes the option as empty β€” no gift value yet
    • D. It means the gift always equals the boolean false
  5. Predict the output. `var BonusLife : ?int = false` and then: ```verse if (Extra := BonusLife?): Print("Awarded {Extra} bonus lives") else: Print("No bonus this round") ```
    • A. Awarded 0 bonus lives
    • B. Awarded false bonus lives
    • C. No bonus this round
    • D. A runtime crash β€” the option is empty
Answer key
  1. B β€” A `?int` holds either nothing (`false`) or an int wrapped in an option. `option{5}` wraps the value 5 into the option. A bare `5` is an int, not a `?int`.
  2. B β€” The real signature is `GetFortCharacter()<transacts><decides>: fort_character`. The `<decides>` effect means it can fail (the player may have no character), and Verse requires `[]` for failable/`<decides>` calls. Calling it with `()` is a compile error.
  3. B β€” Binding `Extra := BonusLife?` succeeds only when the option holds a value, so inside the `then` branch `Extra` is a plain `int` that is proven to exist. You never handle the empty case there β€” that's what the `else` is for.
  4. C β€” In option position, `false` is the *empty option*, not the boolean. `DailyGift : ?daily_gift = false` is a perfectly typed empty `?daily_gift` β€” it has no gift value until something assigns `option{...}` to it.
  5. C β€” `BonusLife` was initialized to `false`, the empty option, and nothing filled it. Binding `Extra := BonusLife?` fails on an empty option, so the `else` branch runs. That's the whole point of options: the empty case is handled honestly instead of crashing.

Recap

One step closer to Barnaby's Jungle Mod-Rally — Safe agent→fort_character and vehicle lookups

Sources

Lesson 13: Tuples: Return Lap AND Time Together

Objectives

Return and destructure tuples for multi-value results.

🧩 Your capstone piece: GetBestLap():(int, float) result

Quiz

  1. How does Verse express "multiple return values" from a single function?
    • A. A `return a, b` statement
    • B. A tuple, e.g. `tuple(logic, logic)`, stated as the last expression
    • C. An array literal `[a, b]`
    • D. The `yield` keyword
  2. Why is `CoinTracker.IsActive[A]` written with square brackets?
    • A. It's an array index
    • B. It's a `<decides>` (fallible) call that may only appear in a failure context
    • C. Brackets are optional styling
    • D. It returns a tuple
  3. What does `CoinTracker.IsActive[A]` actually return on success?
    • A. A `logic` value you test with `?`
    • B. Nothing β€” it succeeds (running the `then:` branch) or fails
    • C. An `int` score
    • D. An option `?logic`
  4. How do you read the two fields of a `tuple(logic, logic)` named `Result`?
    • A. `Result.first` and `Result.second`
    • B. `Result(0)` and `Result(1)`
    • C. `Result[0]` and `Result[1]`
    • D. `Result.A` and `Result.B`
  5. Why does `CoinTracker.GetValue(A)` use parentheses instead of square brackets?
    • A. It's a `<decides>` call
    • B. It returns an `int` directly and is not fallible
    • C. Parentheses are wrong here
    • D. It's an array access
Answer key
  1. B β€” Verse has no multi-return statement; you pack values into a tuple and read them back by field index.
  2. B β€” `IsActive` is `<decides>`; `[]` fallible calls are only legal inside failure contexts like an `if` condition.
  3. B β€” A `<decides>` function succeeds or fails as control flow; the success itself is the 'return', not a `logic`.
  4. B β€” Tuple fields are accessed by numeric index with parentheses: `Result(0)`, `Result(1)`.
  5. B β€” `GetValue` overloads return an `int`; non-fallible calls use `()` parens.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” GetBestLap():(int, float) result

Sources

Lesson 14: Named Tuple Elements: Readable Results

Objectives

Access tuple elements by position and keep multi-value returns readable.

🧩 Your capstone piece: Readable (Position, Points) podium results

Quiz

  1. The event is declared `ClassChangedEvent : listenable(tuple(agent, int))`. What must your subscribed handler's parameter list look like?
    • A. Two params: (Agent : agent, ClassIndex : int)
    • B. One param of type tuple(agent, int)
    • C. One param of type ?agent
    • D. No parameters β€” you read the values from a global
  2. Given `Payload : tuple(agent, int)`, how do you get the class index?
    • A. Payload(0)
    • B. Payload.int
    • C. Payload(1)
    • D. Payload[1]?
  3. Why does `Turret.SetDamage(75)` fail to compile?
    • A. SetDamage is private
    • B. SetDamage takes a float, and Verse doesn't auto-convert int to float
    • C. You must pass a message, not a number
    • D. The turret must be enabled first
  4. `Turret.GetTarget()` returns `?agent`. What do you do before using the result as an agent?
    • A. Nothing β€” it's already an agent
    • B. Cast it with agent(...)
    • C. Unwrap the optional, e.g. if (T := Turret.GetTarget?):
    • D. Call ClearTarget() first
  5. The VFX spawner's `EffectEnabledEvent` is `listenable(tuple())`. What does its handler receive?
    • A. An agent
    • B. An empty tuple carrying no data β€” a pure signal
    • C. A float duration
    • D. The device that fired it
Answer key
  1. B β€” A subscribed handler receives the tuple whole as a single parameter of type tuple(agent, int); you then destructure it with Payload(0) and Payload(1).
  2. C β€” Tuple elements are accessed by position. Index 0 is the agent, index 1 is the int class index.
  3. B β€” SetDamage(Damage:float) requires a float; pass 75.0. Verse never auto-converts between int and float.
  4. C β€” ?agent is an optional and may be empty. Unwrap it with the ? operator inside an if before treating it as an agent.
  5. B β€” tuple() is an empty tuple: the event carries no payload, so the handler declares (Payload : tuple()) and simply reacts to the signal.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Readable (Position, Points) podium results

Sources

Lesson 15: GetRandomFloat / GetRandomInt: Roll the Mod Box

Objectives

Generate random ints/floats for loot tiers, spawn chances, and shuffles.

🧩 Your capstone piece: Random mod-tier roll and banana-boost spawn chance

Quiz

  1. What range of values can GetRandomInt(0, 3) actually produce?
    • A. 0, 1, 2, or 3 β€” both bounds are inclusive, so that's four possible values
    • B. 0, 1, or 2 β€” the upper bound is exclusive
    • C. 1, 2, or 3 β€” the lower bound is exclusive
    • D. 0, 1, 2, 3, or 4 β€” the upper bound is padded by one
  2. Which using{} import do GetRandomInt and GetRandomFloat require?
    • A. using { /Verse.org/Random }
    • B. using { /Fortnite.com/Random }
    • C. using { /Verse.org/Simulation }
    • D. using { /UnrealEngine.com/Math }
  3. You want a banana boost to spawn 35% of the time a racer passes the gate. Which roll-and-check is correct?
    • A. Roll := GetRandomFloat(0.0, 1.0), then if (Roll < 0.35) spawn the item
    • B. Roll := GetRandomInt(0, 35), then if (Roll = 35) spawn the item
    • C. Roll := GetRandomFloat(0.0, 0.35), then always spawn the item
    • D. Roll := GetRandomFloat(0.0, 100.0), then if (Roll < 0.35) spawn the item
  4. What does Shuffle(Checkpoints) from /Verse.org/Random do?
    • A. Returns a NEW array with the same elements in random order β€” the original array is unchanged
    • B. Reorders the Checkpoints array in place
    • C. Returns one random element from the array
    • D. Sorts the array in random-seeded ascending order
  5. A racer passes the Zipline Run gate, BananaChance is 0.35, and GetRandomFloat(0.0, 1.0) returns 0.80. What does the mod_roll_gate do?
    • A. Skips the spawn and prints "No banana this time. Rolled 0.8..." β€” 0.80 is not less than 0.35
    • B. Spawns the banana boost β€” 0.80 is a high roll, and high rolls win
    • C. Spawns the banana boost β€” the comparison is Roll > BananaChance
    • D. Crashes, because GetRandomFloat cannot return a value above BananaChance
Answer key
  1. A β€” GetRandomInt(Low, High) is inclusive on BOTH ends. GetRandomInt(0, 3) returns 0, 1, 2, or 3 β€” four possible values. The possible-outcome count is High - Low + 1, which trips up anyone used to exclusive upper bounds in other languages.
  2. A β€” GetRandomFloat, GetRandomInt, and Shuffle all live in the /Verse.org/Random module. Without that using line the compiler reports the functions as unknown identifiers.
  3. A β€” Rolling a float uniformly in [0.0, 1.0] and comparing against a threshold gives that threshold as the probability: rolls below 0.35 happen about 35% of the time. GetRandomInt(0, 35) = 35 would fire roughly 1 time in 36, and rolling 0.0..100.0 against 0.35 would almost never fire.
  4. A β€” Shuffle(Input:[]t) makes a new array with the same elements shuffled into random order. It never mutates the input. To pick one random element, shuffle and take index [0] inside an if, since array indexing is failable.
  5. A β€” The spawn check is if (Roll < BananaChance). A roll of 0.80 against a 0.35 threshold fails the comparison, so the else branch runs and prints the no-banana message. Only rolls BELOW the threshold spawn the pickup β€” that's what makes the threshold equal the probability.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Random mod-tier roll and banana-boost spawn chance

Sources

Lesson 16: Player Position: Distance to the Finish Line

Objectives

Read GetTransform().Translation, compute distance between players and props.

🧩 Your capstone piece: Finish-line proximity check and nearest-checkpoint helper

Quiz

  1. The finish line sits at (0, 0, 0). Racer A stands at (300, 400, 0) and Racer B stands at (0, 0, 600). Who is closer to the finish?
    • A. Racer A β€” Distance is Sqrt(300Β² + 400Β²) = 500 cm, versus 600 cm for Racer B.
    • B. Racer B β€” a single axis always beats two axes combined.
    • C. They are exactly tied at 500 cm each.
    • D. It cannot be computed without knowing which direction each racer is facing.
  2. Which using{} import gives you Distance(), DistanceXY(), and the vector3 type?
    • A. using { /UnrealEngine.com/Temporary/SpatialMath }
    • B. using { /Fortnite.com/Devices }
    • C. using { /Verse.org/Simulation }
    • D. using { /Fortnite.com/Characters }
  3. Why is the call written P.GetFortCharacter[] with square brackets instead of parentheses?
    • A. The call is failable β€” a player mid-respawn has no character body, so it must be checked inside an if.
    • B. Square brackets mean the call returns an array of characters.
    • C. Square brackets make the call run asynchronously.
    • D. It is legacy syntax; parentheses work identically.
  4. You only need to know WHICH of two racers is closer to the finish, not the actual distances. What is the cheapest correct approach?
    • A. Compare DistanceSquared() results β€” squaring preserves ordering, so the winner is the same and you skip the square root.
    • B. Compare Distance() results β€” DistanceSquared() can rank the racers in the wrong order.
    • C. Add the X, Y, and Z differences together and compare the sums.
    • D. Compare only the X coordinates, since racetracks run along one axis.
  5. In the device, FinishRadius defaults to 500.0. How wide is that finish zone in real-world terms?
    • A. 500 metres β€” half a kilometre around the arch.
    • B. 5 metres β€” UEFN distances are measured in centimetres, so 500.0 cm = 5 m.
    • C. 50 centimetres β€” Verse floats are always expressed in decimetres.
    • D. It depends on the island's scale settings.
Answer key
  1. A β€” Straight-line distance is the length of the difference vector: for A that is Sqrt(300Β² + 400Β² + 0Β²) = 500 cm; for B it is Sqrt(0Β² + 0Β² + 600Β²) = 600 cm. Facing direction is irrelevant β€” Distance() only compares positions.
  2. A β€” The spatial-math toolkit β€” vector3, transform, Distance, DistanceXY, DistanceSquared β€” lives in /UnrealEngine.com/Temporary/SpatialMath. Forget it and every position line in this lesson fails to resolve.
  3. A β€” In Verse, square brackets mark a failable call. GetFortCharacter[] produces a fort_character only if the player currently has a live body; wrapping it in if (Body := P.GetFortCharacter[]) safely skips anyone without one.
  4. A β€” If a < b then aΒ² < bΒ² for non-negative distances, so comparing squared distances always picks the same winner while skipping the Sqrt. Summing axis differences or comparing one axis gives wrong answers on any diagonal course.
  5. B β€” Distances in UEFN are measured in centimetres, so 500.0 means five metres. Forgetting that conversion is the number-one source of 'my trigger radius is the size of a coconut' bugs.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Finish-line proximity check and nearest-checkpoint helper

Sources

Lesson 17: Classes & Structs: Model the Racer

Objectives

Define rally_racer class and mod_reward struct, instantiate, and choose class vs struct.

🧩 Your capstone piece: rally_racer class + mod_reward struct data model

Quiz

  1. In Verse, what is an 'instance'?
    • A. The blueprint itself
    • B. One specific object created from a class
    • C. A type of loop
    • D. An import statement
  2. Which best describes a struct compared to a class?
    • A. A struct holds behavior but no data
    • B. A struct is a simple data box with no behavior
    • C. A struct can only be used for players
    • D. A struct replaces creative_device
  3. Why is GetPlayerUI[Player] written with square brackets?
    • A. It's an array literal
    • B. It's a fallible (<decides>) call and must be in a failure context
    • C. Square brackets concatenate strings
    • D. It's a comment
  4. How do you read the Name field of a hero_info value H?
    • A. H->Name
    • B. H::Name
    • C. H.Name
    • D. GetName(H)
  5. How is a struct value constructed in the code?
    • A. MakeHeroInfo(...)
    • B. hero_info{ Name := ..., Power := ... }
    • C. new hero_info()
    • D. [Name, Power]
Answer key
  1. B β€” A class is the template; an instance is one concrete object stamped from it.
  2. B β€” Structs group related fields; behavior lives in classes/functions.
  3. B β€” [] denotes a fallible call, so it must appear inside an if/for condition.
  4. C β€” Struct fields are accessed with dot notation.
  5. B β€” Use the type name followed by braces with field := value pairs.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” rally_racer class + mod_reward struct data model

Sources

Lesson 18: Abstract Classes & Override: The Checkpoint Family

Objectives

Define an abstract base_checkpoint with an overridden OnPassed per subclass.

πŸ” Builds on: south-shores override-method reference (sunny-dock)

🧩 Your capstone piece: base_checkpoint β†’ speed_gate / mod_gate / finish_gate subclasses

Quiz

  1. Which specifier marks a Verse class as abstract?
    • A. <abstract>
    • B. <interface>
    • C. <virtual>
    • D. <base>
  2. You have an abstract method `Activate()<suspends>:void` in a base class. What MUST the concrete subclass write?
    • A. Activate<override>()<suspends>:void = { ... }
    • B. Activate():void = { ... }
    • C. override Activate()<suspends>:void { ... }
    • D. Activate<virtual>()<suspends>:void = { ... }
  3. Why must you write `spawn { H.Activate() }` when iterating a `[]arena_hazard` array and calling a `<suspends>` method?
    • A. Because a `for` loop body is not a suspending context, so suspending calls must run in their own spawned task.
    • B. Because `spawn` is required for all method calls on abstract types.
    • C. Because `for` loops in Verse are always synchronous and cannot call any methods.
    • D. Because `<suspends>` methods can only be called from `OnBegin`.
  4. What is the key difference between an abstract class and an interface in Verse?
    • A. An abstract class can have data fields and method bodies; an interface cannot.
    • B. An interface can be instantiated directly; an abstract class cannot.
    • C. Abstract classes support multiple inheritance; interfaces do not.
    • D. There is no difference β€” they are interchangeable.
  5. You want a polymorphic array holding both `vfx_hazard` and `channel_hazard` instances (both extend `arena_hazard`). Which declaration is correct?
    • A. Hazards : []arena_hazard = array{VFXHazard, ChannelHazard}
    • B. Hazards := array{VFXHazard, ChannelHazard}
    • C. Hazards : []creative_device = array{VFXHazard, ChannelHazard}
    • D. Hazards : []vfx_hazard = array{VFXHazard, ChannelHazard}
Answer key
  1. A β€” The `<abstract>` specifier on a class declaration tells Verse the class cannot be instantiated directly and that subclasses must provide concrete implementations of its abstract methods.
  2. A β€” Verse requires the `<override>` specifier and the effect specifiers must match exactly. Without `<override>` the method shadows rather than overrides, breaking polymorphic dispatch.
  3. A β€” A `for` loop body does not itself carry the `<suspends>` effect, so you cannot directly `await` or call suspending functions inside it. `spawn` launches each call as an independent concurrent task.
  4. A β€” Abstract classes may contain field declarations and default method implementations. Interfaces in Verse are purely structural contracts with no data or implementation bodies.
  5. A β€” You must explicitly annotate the array type as `[]arena_hazard` so Verse knows to treat both elements as the abstract base type. Without the annotation the compiler infers a narrower or conflicting type and rejects the mixed array.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” base_checkpoint β†’ speed_gate / mod_gate / finish_gate subclasses

Sources

Lesson 19: Interfaces: Anything Can Be Scoreable

Objectives

Declare and implement an interface so unrelated classes share a contract.

🧩 Your capstone piece: scoreable interface implemented by racer and checkpoint

Quiz

  1. You have a class `my_wrapper` that implements the `dock_activatable` interface. The interface declares `Activate(Agent:agent):void`. Which method declaration in `my_wrapper` will the compiler accept?
    • A. Activate<override>(Agent:agent):void = ...
    • B. Activate(Agent:agent):void = ...
    • C. override Activate(Agent:agent):void = ...
    • D. Activate<implements>(Agent:agent):void = ...
  2. You subscribe to `trigger_device.TriggeredEvent`. What is the correct handler signature?
    • A. (Agent : agent) : void
    • B. (MaybeAgent : ?agent) : void
    • C. (MaybeAgent : option(agent)) : void
    • D. () : void
  3. Which call correctly shows a localized custom message to a specific agent for 4 seconds using `hud_message_device`?
    • A. Banner.Show(Agent, "Dock Secured!", ?DisplayTime := 4.0)
    • B. Banner.SetText("Dock Secured!") then Banner.Show(Agent)
    • C. Banner.Show(Agent, MyText("Dock Secured!"), ?DisplayTime := 4.0)
    • D. Banner.Show(MyText("Dock Secured!"))
  4. You call `DockPlate.SetMaxTriggerCount(50)` to allow 50 activations. What actually happens?
    • A. The trigger allows exactly 50 activations.
    • B. The trigger allows unlimited activations because 50 > 20.
    • C. The trigger allows 20 activations because the value is clamped to [0, 20].
    • D. The call throws a runtime error.
  5. Why can't you mark an interface data member with `@editable`?
    • A. Interfaces only allow method declarations, never data members.
    • B. `@editable` requires a concrete device type and a physical placement in UEFN; interface members are abstract contracts with no backing instance.
    • C. You can use `@editable` on interface members if you also add `<public>`.
    • D. `@editable` is only valid inside `OnBegin`.
Answer key
  1. A β€” Verse requires the `<override>` specifier on any method that satisfies an interface contract. Without it the method is treated as a new, unrelated method and the class fails to implement the interface.
  2. B β€” `TriggeredEvent` is typed `listenable(?agent)`, so the subscribed callback receives a `?agent` (option agent). You must unwrap it with `if (Agent := MaybeAgent?)` before using it as a plain `agent`.
  3. C β€” The three-parameter `Show` overload requires a `message` value (not a raw string). You must pass a localized helper result like `MyText("...")` declared with `<localizes>`. Option A passes a raw string (type error); option D omits the agent.
  4. C β€” `SetMaxTriggerCount` clamps its input to the range [0, 20]. Passing 50 silently results in a max of 20. Use 0 for unlimited triggers.
  5. B β€” `@editable` wires a field to the UEFN editor's Details panel and requires a concrete, placeable device type. Interface members are abstract β€” they have no concrete backing object β€” so `@editable` is not valid there. Declare `@editable` on the concrete class fields, then wrap them in interface-implementing objects at runtime.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” scoreable interface implemented by racer and checkpoint

Sources

Lesson 20: Modules: Organize the Jungle Codebase

Objectives

Split code into modules, control access, and use using { } imports.

🧩 Your capstone piece: Module layout of the whole rally project

Quiz

  1. You wrote a function `Repeat(...)` (no access specifier) in your `Utils` module, did `using { Verse.Scripts.Utils }` in a device, but the compiler says `Repeat` is unknown. What's wrong?
    • A. The using statement is in the wrong place
    • B. `Repeat` has no `<public>` specifier, so it isn't visible outside its module β€” you must mark it `<public>` to share it
    • C. Functions can't be put in modules
    • D. You must call it as `Utils.Repeat[...]` with square brackets
  2. What does a `using` statement actually do?
    • A. Copies the file's code into the current file
    • B. Opens a module (namespace) so its public names can be written unqualified
    • C. Compiles the module ahead of time
    • D. Marks the current file as public
  3. In `permissions.verse`, `Unused<internal> := module:` is nested inside `Scripts`. Who can see `Unused`?
    • A. Any file in the whole project
    • B. Only code within the `Scripts` module (and its submodules) β€” `<internal>` keeps it private to its module
    • C. No one; <internal> modules are disabled
    • D. Only the file that declares it
  4. Why are `/Fortnite.com/Devices` and `Verse.Scripts.Utils` opened the same way (with `using`)?
    • A. They aren't β€” Epic paths use `import`, project paths use `using`
    • B. Because both are module paths; Epic's are absolute (leading slash, from the engine root), project ones are relative, but both are modules opened by `using`
    • C. Because all Verse code lives in one global module
    • D. Because `using` only works on Epic modules and project ones are special-cased
  5. The article's `Repeat` helper builds its result with `for (I := 0..Times - 1): set Result += Text`. What does `Repeat("ab", 3)` return?
    • A. "abab" β€” the range 0..Times-1 runs Times-1 iterations
    • B. "ab" β€” the loop body runs once regardless of Times
    • C. "ababab" β€” 0..2 iterates three times (I = 0, 1, 2), appending "ab" each pass
    • D. "abababab" β€” ranges in Verse are inclusive of Times
Answer key
  1. B β€” A member with no access specifier is NOT automatically public β€” it's more restricted. To use it across modules you must explicitly mark it `<public>`. This is the single most common module mistake: opening the module with `using` but never publishing the name.
  2. B β€” `using` opens a MODULE β€” a namespace β€” bringing its public names into scope so you can write them without the full path. It's the same mechanism for Epic's APIs (`/Fortnite.com/Devices`) and your own systems (`Verse.Scripts.Utils`). It does not copy files.
  3. B β€” `<internal>` makes a name visible only within its own module and submodules β€” here, inside `Scripts`. Other top-level systems and game code cannot reach it. `<public>` would be needed to expose it project-wide.
  4. B β€” There's one mechanism. Both are module paths; `using` opens either. Epic's begin with a slash (absolute, from the engine root) while your project's are named after your folder tree, but conceptually they're the same: bring a module's public names into scope.
  5. C β€” The range `0..Times - 1` with Times = 3 is 0..2, which yields I = 0, 1, 2 β€” three iterations. Each appends "ab" to Result, giving "ababab". Writing `0..Times - 1` (not `0..Times`) is exactly how you get Times repetitions.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Module layout of the whole rally project

Sources

Lesson 21: Build CodewoodKit: Your First Shared Module

Objectives

Author a reusable helper module (FormatTime, Distance, PickRandom) that later zones import β€” the start of the cross-zone module arc.

🧩 Your capstone piece: CodewoodKit module β€” exported to east-volcano/west-coves/the-deeps

Quiz

  1. In `PotionData.verse`, which keyword tells Verse the file is a library of reusable code rather than standalone game logic?
    • A. module
    • B. library
    • C. package
    • D. namespace
  2. MainGame.verse needs to read the potion stats stored in the PotionData module. Which line makes that possible?
    • A. import PotionData
    • B. include PotionData
    • C. using PotionData
    • D. require PotionData
  3. Given the module declares `HealAmount<public> : int = 50`, what does `Print($"Heal Amount: {PotionData.HealAmount}")` write to the Output Log?
    • A. Heal Amount: PotionData.HealAmount
    • B. Heal Amount: 50
    • C. Heal Amount: 50.0
    • D. Nothing β€” you cannot print module values
  4. You write a module with `SwordDamage : int = 25` inside it, but the importing script cannot see `SwordDamage` at all. What is the bug?
    • A. The variable name must start with a lowercase letter
    • B. Module variables must be declared with var
    • C. SwordDamage is missing the <public> specifier, so it stays hidden inside the module
    • D. int values cannot be shared between files
  5. In the declaration `PotionName<public><localizes>:message = "Health Potion"`, what does the `<localizes>` specifier do?
    • A. It restricts the text to one region of the island
    • B. It allows the text to be translated into different languages later
    • C. It makes the variable readable by other modules
    • D. It stores the text on the local machine only
Answer key
  1. A β€” The tutorial defines the loot-pool file with `PotionData<public> := module:` β€” the `module` keyword marks it as a unit of code other scripts can import, not a script that runs on its own.
  2. C β€” Verse imports a module with the `using` statement. `using PotionData` is how MainGame.verse 'equips' the module; `import`, `include`, and `require` come from other languages.
  3. B β€” `PotionData.HealAmount` reaches into the module and pulls out the int value 50, so the interpolated string prints `Heal Amount: 50`. It is an `int`, so there is no `.0` β€” that would be the float `CooldownTime`.
  4. C β€” By default, code inside a module is private (hidden). The tutorial marks every shared value β€” `PotionName`, `HealAmount`, `CooldownTime` β€” with `<public>`, the 'Take Me!' sign that lets importing scripts read it.
  5. B β€” `<localizes>` marks the message for translation β€” the article compares it to subtitles in a cutscene. It is `<public>` that exposes the value to other scripts, not `<localizes>`.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” CodewoodKit module β€” exported to east-volcano/west-coves/the-deeps

Sources

Lesson 22: Trigger Device: Checkpoint Sensors

Objectives

Reference a trigger_device with @editable and Subscribe to TriggeredEvent in Verse.

πŸ” Builds on: center-village town-plaza trigger wiring pattern

🧩 Your capstone piece: Checkpoint trigger sensors along the rally route

Quiz

  1. What type does the trigger_device's TriggeredEvent hand to your subscribed handler?
    • A. agent
    • B. ?agent (an optional agent)
    • C. player
    • D. fort_character
  2. Why must you declare the trigger as an @editable field inside your creative_device class?
    • A. To make it run faster
    • B. So you can bind it to the placed device and call its methods; a bare Device.Method() fails
    • C. Because TriggeredEvent only works on editable fields
    • D. It is optional and only for readability
  3. What value passed to SetMaxTriggerCount means 'no limit'?
    • A. 20
    • B. -1
    • C. 0
    • D. 100
  4. What does GetTriggerCountRemaining() return when the device's max trigger count is unlimited?
    • A. The number of players in the game
    • B. 20
    • C. 0
    • D. An error
  5. Which call fires the device's TriggeredEvent from code while attaching a specific player?
    • A. Trigger()
    • B. Trigger(Agent)
    • C. Enable()
    • D. SetTransmitDelay(Agent)
Answer key
  1. B β€” TriggeredEvent is listenable(?agent) because the device can also be fired from code with no agent, so you must unwrap the option before using it.
  2. B β€” Calling a method on a placed device requires an @editable field you point at the device in the Details panel; otherwise you get 'Unknown identifier'.
  3. C β€” 0 indicates unlimited triggers. The argument is clamped between 0 and 20.
  4. C β€” Per the API, it returns 0 when GetMaxTriggerCount is unlimited, so don't treat 0 as 'empty' in that configuration.
  5. B β€” Trigger(Agent:agent) fires the event and passes that agent along; the agentless Trigger() fires with no agent.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Checkpoint trigger sensors along the rally route

Sources

Lesson 23: Cable Splitter: One Signal, Many Reactions

Objectives

Fan one event out to multiple devices, and when to do it in Verse instead.

🧩 Your capstone piece: Checkpoint hit β†’ SFX + drum + HUD fan-out

Quiz

  1. Which import is required to use `cable_splitter_device` in Verse?
    • A. using { /Fortnite.com/Devices/Patchwork }
    • B. using { /Fortnite.com/Devices/Splitters }
    • C. using { /Verse.org/Simulation }
    • D. using { /UnrealEngine.com/Temporary }
  2. What does calling `Splitter.Disable()` in `OnBegin` accomplish?
    • A. It destroys the splitter device permanently.
    • B. It guarantees the splitter starts in a known off state regardless of its editor setting.
    • C. It prevents the splitter from ever being enabled again.
    • D. It unsubscribes all downstream Patchwork connections.
  3. How do you correctly mutate the `FragmentsCollected` counter in Verse?
    • A. FragmentsCollected += 1
    • B. FragmentsCollected = FragmentsCollected + 1
    • C. set FragmentsCollected = FragmentsCollected + 1
    • D. FragmentsCollected.Increment()
  4. A `trigger_device.TriggeredEvent` is a `listenable(?agent)`. What must your handler's parameter type be?
    • A. agent
    • B. player
    • C. ?agent
    • D. fort_character
  5. What happens to downstream Patchwork devices when `Splitter.Disable()` is called?
    • A. They are also disabled individually.
    • B. Signals from the upstream source no longer pass through the splitter to the outputs.
    • C. The splitter's wiring is permanently removed.
    • D. The downstream devices are paused until re-enabled.
Answer key
  1. A β€” `cable_splitter_device` is declared inside the Patchwork module, so `using { /Fortnite.com/Devices/Patchwork }` is the required import. Without it the type is unknown to the compiler.
  2. B β€” The editor's default state might differ between team members or after copy-paste. Calling `Disable()` in `OnBegin` locks in a known starting state at runtime.
  3. C β€” Verse requires the `set` keyword to assign a new value to a mutable `var`. Omitting `set` is a compile error.
  4. C β€” Because `TriggeredEvent` is typed `listenable(?agent)`, the subscribed handler must accept `?agent` (an optional agent). Passing a plain `agent` parameter will cause a type mismatch compile error.
  5. B β€” `Disable()` blocks signal propagation through the splitter. The downstream devices themselves remain in their current state β€” they simply stop receiving new signals from this splitter.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Checkpoint hit β†’ SFX + drum + HUD fan-out

Sources

Lesson 24: Player Reference Device: Spotlight the Leader

Objectives

Capture and display a specific player (race leader) with player_reference_device.

🧩 Your capstone piece: Leader podium/statue display at Verdant Hollow

Quiz

  1. Which method do you call to store a specific player in the player_reference_device so it begins tracking them?
    • A. Register(Agent)
    • B. Enable()
    • C. GetAgent()
    • D. Track(Agent)
  2. What is the correct way to call `IsReferenced` in Verse?
    • A. if (MyRef.IsReferenced[SomeAgent]):
    • B. MyRef.IsReferenced(SomeAgent)
    • C. if (MyRef.IsReferenced(SomeAgent) = true):
    • D. let result = MyRef.IsReferenced(SomeAgent)
  3. What does `Activate()` do on the player_reference_device?
    • A. It ends the round/game AND signals ActivatedEvent with the stored agent
    • B. It registers the local player as the tracked agent
    • C. It enables the device so it can accept new agents
    • D. It clears the stored agent and resets all stats
  4. What type do the player_reference_device's events (e.g., TrackedStatChangedEvent) send to their handlers?
    • A. A plain `agent` (not optional)
    • B. An optional `?agent`
    • C. A `player` type
    • D. An `int` stat value
  5. What is the difference between AgentUpdatedEvent and AgentReplacedEvent?
    • A. AgentUpdatedEvent fires on any change including first registration; AgentReplacedEvent fires only when a previously stored agent is swapped out
    • B. AgentReplacedEvent fires on any change; AgentUpdatedEvent fires only on the first registration
    • C. They are identical β€” both fire whenever Register is called
    • D. AgentUpdatedEvent fires when GetAgent is called; AgentReplacedEvent fires when Clear is called
Answer key
  1. A β€” `Register(Agent:agent)` is the method that stores an agent in the device and starts tracking their configured stat. `Enable` just turns the device on, `GetAgent` reads the stored agent, and `Track` does not exist on this device.
  2. A β€” `IsReferenced` is marked `<decides>`, making it a failable expression. In Verse, failable expressions must appear inside an `if` condition using bracket syntax: `if (MyRef.IsReferenced[SomeAgent]):`.
  3. A β€” According to the API, `Activate()` ends the round/game. It also signals `ActivatedEvent`, sending the currently stored agent to any subscribers. It does not register players, enable the device, or clear state.
  4. A β€” All five events on `player_reference_device` are typed `listenable(agent)` β€” they send a plain, non-optional `agent`. This differs from devices like `trigger_device` which send `?agent`. Your handler must be declared as `OnHandler(A : agent) : void`.
  5. A β€” AgentUpdatedEvent signals whenever the stored agent changes to a new value, including the very first registration. AgentReplacedEvent signals only when an agent that was already stored gets replaced by a different one β€” useful for detecting swaps in a bounty or leaderboard system.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Leader podium/statue display at Verdant Hollow

Sources

Lesson 25: Player Counter: The Starting-Grid Gate

Objectives

Gate game flow on how many players are in a zone (lobby ready-check).

🧩 Your capstone piece: Lobby gate: race starts only when all racers are on the grid

Quiz

  1. What is the correct handler signature for `CountSucceedsEvent`?
    • A. (Unused : tuple()) : void
    • B. (Agent : agent) : void
    • C. (Agent : ?agent) : void
    • D. () : void
  2. You call `SetTargetCount(6)` at runtime. What else should you call immediately after if you want the device to evaluate the new target right now?
    • A. CompareToTarget()
    • B. TransmitForAllCounted()
    • C. Enable()
    • D. GetCount()
  3. Which method returns an array of every agent currently being counted by the device?
    • A. GetCountedAgents()
    • B. GetCount()
    • C. TransmitForAllCounted()
    • D. IsCounted(Agent)
  4. Why must `IsPassingTest[]` be called inside an `if` expression?
    • A. It is marked `<decides>`, meaning it can fail, and failable expressions must appear in a failure-handling context.
    • B. It returns a `bool` that must be explicitly cast.
    • C. It is an async method that requires `<suspends>`.
    • D. It only works after `CompareToTarget()` has been called at least once.
  5. You want only specific VIP players to count toward the extraction trigger. Which methods should you use?
    • A. `Register(Agent)` to add them and `UnregisterAll()` to clear between rounds.
    • B. `SetTargetCount(1)` alone is sufficient.
    • C. `IsCounted(Agent)` to add them to the count.
    • D. `TransmitForAllCounted()` followed by `GetCountedAgents()`.
Answer key
  1. A β€” `CountSucceedsEvent` is typed `listenable(tuple())`, so its handler must accept a `tuple()` parameter. Only `CountedEvent` and `RemovedEvent` carry an `agent`.
  2. A β€” `CompareToTarget()` forces an immediate evaluation of current count vs. target, signalling `CountSucceedsEvent` or `CountFailsEvent` right away rather than waiting for the next tick.
  3. A β€” `GetCountedAgents()` returns `[]agent` β€” the full list of agents currently counted. `GetCount()` returns only the integer count, and `IsCounted` checks a single agent.
  4. A β€” Methods marked `<decides>` are failable in Verse. They must be used inside `if`, `for`, or another failure-handling context β€” calling them bare is a compile error.
  5. A β€” `Register(Agent)` adds a specific agent to the registered player list (combined with the zone tracking per the editor's *Track Registered Players* setting), and `UnregisterAll()` clears the list cleanly between rounds.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Lobby gate: race starts only when all racers are on the grid

Sources

Lesson 26: Speaker Device: Jungle Fanfare

Objectives

Play positional audio from Verse on game events.

🧩 Your capstone piece: Checkpoint fanfare and finish-line horn

Quiz

  1. Which import is required to reference `speaker_device` in Verse?
    • A. using { /Fortnite.com/Devices/Patchwork }
    • B. using { /Fortnite.com/Devices/Audio }
    • C. using { /Verse.org/Audio }
    • D. using { /Fortnite.com/Devices }
  2. What does `speaker_device.Disable()` return?
    • A. void β€” it has no return value
    • B. logic β€” true if the device was previously enabled
    • C. A cancelable token you can use to re-enable later
    • D. It suspends until the audio fades out
  3. You want the speaker to be silent at round start and only play during active gameplay. Where should you call `speaker_device.Disable()` to guarantee this?
    • A. In `OnBegin`, before subscribing to any events
    • B. In the UEFN Details panel by unchecking Start Enabled β€” no Verse call needed
    • C. In a separate `spawn` block after OnBegin returns
    • D. You cannot disable a speaker before the first player joins
  4. Which of the following is TRUE about `speaker_device` events?
    • A. `speaker_device` has no events; all logic must be driven by external device events
    • B. `speaker_device` fires an `AudioStartedEvent` when audio begins playing
    • C. `speaker_device` fires a `CompletedEvent` when the audio clip finishes
    • D. `speaker_device` fires a `TriggeredEvent` similar to `trigger_device`
  5. A `trigger_device.TriggeredEvent` handler receives `Agent : ?agent`. You want to call `MySpeaker.Enable()` only when a real player triggers it. Which code is correct?
    • A. if (A := Agent?): MySpeaker.Enable()
    • B. MySpeaker.Enable(Agent)
    • C. if (Agent <> false): MySpeaker.Enable()
    • D. MySpeaker.Enable() # ?agent is automatically unwrapped
Answer key
  1. A β€” `speaker_device` is declared inside the `/Fortnite.com/Devices/Patchwork` module. Without that `using` directive the compiler reports 'Unknown identifier' for `speaker_device`.
  2. A β€” `Disable():void` is a plain, synchronous method. It returns nothing and does not suspend, so you call it as a bare statement with no await.
  3. A β€” Calling `Disable()` inside `OnBegin` makes Verse the single source of truth for initial state, overriding whatever the editor's Start Enabled checkbox says.
  4. A β€” The `speaker_device` API surface contains only `Enable` and `Disable` β€” no events at all. You must react to external events (triggers, buttons, round manager) and then call those methods.
  5. A β€” `?agent` is an option type. You must unwrap it with `if (A := Agent?):` before using the concrete agent. `Enable()` takes no arguments, so you just call it inside the successful branch.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Checkpoint fanfare and finish-line horn

Sources

Lesson 27: Drum Player: Countdown Beats

Objectives

Drive rhythmic Patchwork-style audio from Verse for pacing cues.

πŸ” Builds on: south-shores drum/omega-synth Patchwork lessons

🧩 Your capstone piece: 3-2-1-GO drum countdown

Quiz

  1. What must you do before you can call `DrumPlayer.Enable()` in Verse?
    • A. Declare DrumPlayer as an @editable field inside your creative_device class and link it to a placed drum_player_device in the UEFN Details panel.
    • B. Import the drum_player_device class at the top of your file with a using statement.
    • C. Call DrumPlayer.Disable() first to reset its state.
    • D. Add a drum_sequencer_device to the same class.
  2. What does calling `DrumPlayer.Enable()` actually do?
    • A. It immediately plays a drum sound effect.
    • B. It makes the device responsive to incoming Patchwork note signals so it can produce audio.
    • C. It starts a built-in drum loop stored inside the device.
    • D. It connects the device to the nearest drum_sequencer_device automatically.
  3. A `trigger_device`'s `TriggeredEvent` handler receives which parameter type?
    • A. agent
    • B. player
    • C. ?agent
    • D. tuple()
  4. Which of the following is TRUE about `drum_player_device` events in Verse?
    • A. It fires a BeatEvent every time a drum note plays.
    • B. It fires an EnabledEvent when Enable() is called.
    • C. It exposes no events β€” you can only call Enable() and Disable() on it.
    • D. It inherits TriggeredEvent from patchwork_device.
  5. Why is it best practice to call `DrumPlayer.Disable()` explicitly in `OnBegin` rather than relying on the editor's default state?
    • A. Verse ignores editor settings entirely at runtime.
    • B. Calling Disable() in OnBegin ensures your code is the single source of truth for initial state, making behaviour predictable regardless of editor configuration.
    • C. The device always starts in an enabled state at runtime no matter what the editor says.
    • D. OnBegin resets all device states automatically, so Disable() is needed to override that reset.
Answer key
  1. A β€” Verse requires every placed device to be referenced through an @editable field. Without it, the identifier is unknown and the code won't compile, let alone run.
  2. B β€” Enable() activates the device's ability to respond to Patchwork note inputs. Audio only plays when note signals arrive from upstream Patchwork devices like a drum_sequencer_device.
  3. C β€” TriggeredEvent is a listenable(?agent), so the handler receives an optional agent. You must unwrap it with `if (A := Agent?):` before using the agent value.
  4. C β€” The drum_player_device API surface only exposes Enable and Disable methods. There are no listenable events on this device.
  5. B β€” Editor defaults can be changed accidentally or differ between team members. Setting state explicitly in OnBegin makes your Verse logic self-contained and reliable.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” 3-2-1-GO drum countdown

Sources

Lesson 28: Custom Events: The CheckpointPassed Event Bus

Objectives

Declare event(payload), Signal it, and Await/Subscribe across classes β€” decoupling checkpoints from the race manager.

🧩 Your capstone piece: CheckpointPassedEvent(racer, index) event bus

Quiz

  1. How do you declare a custom event that carries a player as payload?
    • A. event<agent> = event{}
    • B. BossDefeatedEvent : event(agent) = event(agent){}
    • C. signal(agent) = new signal()
    • D. event[agent] := event[agent]{}
  2. Which verb fires a custom event and runs every subscriber's handler?
    • A. Broadcast(Payload)
    • B. Emit(Payload)
    • C. Signal(Payload)
    • D. Fire(Payload)
  3. Why is GetPlayerUI wrapped in an if with square brackets?
    • A. Because it returns a logic you must test
    • B. Because it is a <decides> (fallible) call that may fail
    • C. Because it modifies state and needs <transacts>
    • D. Because square brackets are just a style choice
  4. What is the correct Subscribe syntax for a button_device's InteractedWithEvent?
    • A. Button.InteractedWithEvent().Subscribe(H)
    • B. Button.InteractedWithEvent.Subscribe(H)
    • C. Button.Subscribe(InteractedWithEvent, H)
    • D. Subscribe(Button.InteractedWithEvent, H)
  5. How do you run a handler every time your custom event(agent) signals?
    • A. BossDefeatedEvent.Listen(Handler)
    • B. BossDefeatedEvent.Subscribe(Handler)
    • C. loop: Winner := BossDefeatedEvent.Await(), then call your handler
    • D. BossDefeatedEvent += Handler
Answer key
  1. B β€” An event's payload type goes in parentheses, and it is initialized with a fresh `event(agent){}`.
  2. C β€” `Signal(Payload)` triggers all subscribed handlers, each receiving the payload.
  3. B β€” `GetPlayerUI[...]` is fallible, so it must be called with `[]` inside a failure context like an `if`.
  4. B β€” Device events do NOT use parentheses before `.Subscribe` β€” only character events like EliminatedEvent do.
  5. C β€” A custom `event(t)` has only `Signal` and `Await` β€” loop on `Await()` in a <suspends> context. Only device events (`listenable`) carry `.Subscribe`.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” CheckpointPassedEvent(racer, index) event bus

Sources

Lesson 29: Item Spawner: Banana Boosts on the Track

Objectives

Spawn pickup items at runtime and cycle what spawns from Verse.

πŸ” Builds on: south-shores spawn-prop lesson (runtime spawning concept)

🧩 Your capstone piece: Banana-boost pickups scattered on the rally route

Quiz

  1. Which method do you call to immediately place the currently configured item on the pad, bypassing any timer?
    • A. SpawnItem()
    • B. Enable()
    • C. CycleToNextItem()
    • D. SetEnableRespawnTimer(Respawn := true)
  2. What is the correct handler signature for ItemPickedUpEvent?
    • A. OnPickup(MaybeAgent : ?agent) : void
    • B. OnPickup(Collector : agent) : void
    • C. OnPickup(Collector : player) : void
    • D. OnPickup() : void
  3. You want the spawner to auto-respawn every 15 seconds after a pickup. Which two calls are required?
    • A. SetTimeBetweenSpawns(15.0) only
    • B. SetEnableRespawnTimer(Respawn := true) and SetTimeBetweenSpawns(15.0)
    • C. Enable() and SpawnItem()
    • D. SetTimeBetweenSpawns(15) and Enable()
  4. What happens if you call SpawnItem() while the item_spawner_device is disabled?
    • A. The item spawns normally.
    • B. A compile error occurs.
    • C. The item does not appear; the call is ignored.
    • D. The device automatically enables itself first.
  5. After CycleToNextItem() is called on a spawner that is already showing its LAST configured item, what happens on the next SpawnItem() call?
    • A. Nothing β€” the spawner stops cycling.
    • B. It spawns the last item again.
    • C. It wraps around and spawns the first item in the list.
    • D. It throws a runtime error.
Answer key
  1. A β€” SpawnItem() forces the current item to materialise on the pad right now, regardless of whether the respawn timer is running or how much time remains.
  2. B β€” ItemPickedUpEvent is typed listenable(agent), so it delivers a plain agent (not ?agent) to the handler. No optional unwrapping is needed.
  3. B β€” SetEnableRespawnTimer turns the auto-respawn feature on, and SetTimeBetweenSpawns sets the interval. Both are needed β€” the timer does nothing if it isn't enabled, and enabling it without setting the time uses whatever value was configured in the editor.
  4. C β€” A disabled spawner ignores SpawnItem() β€” the item will not appear. You must call Enable() before SpawnItem() when the device starts in a disabled state.
  5. C β€” CycleToNextItem() wraps around to the beginning of the Item List when it reaches the end, so the next SpawnItem() will produce the first configured item.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Banana-boost pickups scattered on the rally route

Sources

Lesson 30: Item Granter: Custom Reward Items

Objectives

Grant custom items to a specific player from Verse (the custom-inventory foundation).

🧩 Your capstone piece: Mod-reward grant when a racer passes the mod gate

Quiz

  1. Why must you declare the item granter as an @editable field instead of calling item_granter_device.GrantItem(...) directly?
    • A. Because GrantItem is private
    • B. Because a placed device must be referenced through an @editable field linked in the Details panel; a bare type call is an Unknown identifier error
    • C. Because GrantItem requires the <suspends> effect
    • D. Because Verse devices only work inside structs
  2. What parameter does a handler for ItemGrantedEvent receive?
    • A. An optional agent (?agent) you must unwrap
    • B. A tuple(agent, int)
    • C. An agent, already unwrapped (listenable(agent))
    • D. No parameter at all
  3. How do you read the count from a GrantItemWithCountEvent payload of type tuple(agent, int)?
    • A. Payload.Count
    • B. Payload(1)
    • C. Payload.Second()
    • D. GetCount(Payload)
  4. When does GrantItemToAll() actually grant items?
    • A. Always, regardless of settings
    • B. Only when Receiving Players is set to All or Team Index
    • C. Only when an agent is also passed
    • D. Only when Grant While Offline is Yes
  5. What happens if you call SetNextItem with an index outside the valid range?
    • A. It throws a runtime error
    • B. It grants a random item
    • C. It does nothing
    • D. It clamps to the last item
Answer key
  1. B β€” Placed devices are reached through @editable fields you link in the editor. Calling a method on the bare type name fails to compile.
  2. C β€” ItemGrantedEvent is listenable(agent), so the handler gets (Agent : agent) directly β€” no Agent? unwrap needed.
  3. B β€” Tuple elements are accessed positionally: Payload(0) is the agent, Payload(1) is the int count.
  4. B β€” GrantItemToAll has no agent argument and only functions when Receiving Players is All or Team Index.
  5. C β€” Per the API, calling SetNextItem with an invalid index simply does nothing.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Mod-reward grant when a racer passes the mod gate

Sources

Lesson 31: First Verse UI: Lap Counter HUD

Objectives

Get GetPlayerUI[], AddWidget a text_block, and update it live β€” the START of the UI arc.

πŸ” Builds on: south-shores hud-message feedback pattern (upgraded to real widgets)

🧩 Your capstone piece: Per-racer lap counter HUD widget

Quiz

  1. According to the article, what is a HUD?
    • A. A heads-up display that shows info on screen without blocking the game
    • B. A device that spawns players onto the island
    • C. A special camera mode that follows the player
    • D. A menu that pauses the game while it is open
  2. Which widget type does the tutorial use to put text on the player's screen?
    • A. text_block
    • B. billboard_device
    • C. hud_message_device
    • D. canvas_slot
  3. Which call gets the interface that lets you add widgets to a specific player's screen?
    • A. GetPlayerUI[FortPlayer]
    • B. GetPlayspace().GetPlayers()
    • C. AddWidget(MyText)
    • D. StringToMessage("Welcome!")
  4. What does GetPlayspace().GetPlayers() return in the tutorial code?
    • A. A list of all active players on the island
    • B. Only the player who placed the device
    • C. The player's UI canvas
    • D. The number of players as an integer
  5. Fill in the blank: MyText := text_block: DefaultText := ______("Welcome to my Island!")
    • A. StringToMessage
    • B. ToText
    • C. Print
    • D. MakeWidget
Answer key
  1. A β€” The article describes the HUD as a heads-up display β€” like the frame around a window β€” that shows information while the game world stays visible and playable behind it.
  2. A β€” The script creates `MyText := text_block: DefaultText := ...`. A `text_block` is the widget (the "sticker") that holds words and can be added to the Player UI.
  3. A β€” `GetPlayerUI[FortPlayer]` returns the Player UI β€” the "glass of the window" the widgets get stuck onto. GetPlayers just lists players, and AddWidget/StringToMessage come later in the flow.
  4. A β€” The walkthrough says GetPlayspace().GetPlayers() "returns a list of everyone on the island"; the code then grabs the first entry with `Players[0]`.
  5. A β€” The article uses the `StringToMessage<localizes>` helper to wrap the raw string as a `message`, which is what `DefaultText` expects.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Per-racer lap counter HUD widget

Sources

Lesson 32: Canvas Layout: The Rally HUD Panel

Objectives

Compose a canvas with anchored slots for lap, boost meter, and position.

πŸ” Builds on: lesson 31 widget code (extends the same ui module)

🧩 Your capstone piece: Full rally HUD: laps + boosts + race position in one canvas

Quiz

  1. How do you display a canvas on a specific player's screen?
    • A. canvas.Show(Player)
    • B. Get the player_ui via GetPlayerUI[Player], then call UI.AddWidget(canvas)
    • C. canvas.AddToScreen()
    • D. Print the canvas to the log
  2. Why must GetPlayerUI be called inside an if with square brackets?
    • A. It is a suspends function that must be awaited
    • B. It is a <decides> function that can fail and returns a player_ui only on success
    • C. Square brackets are just a style preference
    • D. It only works in OnBegin
  3. What does DefaultText on a text_block expect, and how do you supply it?
    • A. A raw string literal like "Hi"
    • B. A message value, created via a <localizes> helper function
    • C. An int converted with StringToMessage
    • D. A color struct
  4. You added a canvas earlier and now want to take it back down. What do you need?
    • A. Nothing β€” canvases auto-remove
    • B. The exact widget reference passed to AddWidget, given to RemoveWidget
    • C. Call canvas.Destroy()
    • D. Re-run OnBegin
  5. Within a canvas, how is a child widget's screen position controlled?
    • A. By calling canvas.SetPosition
    • B. Through a canvas_slot's Anchors (screen fractions) and Offsets (pixels)
    • C. The canvas ignores position entirely
    • D. By listening to the canvas's OnMoved event
Answer key
  1. B β€” UI is per-player: fetch the player_ui with GetPlayerUI (a <decides> call) and call AddWidget on it. The canvas itself has no display method.
  2. B β€” GetPlayerUI<transacts><decides> can fail if no UI is associated with the player, so it must be used in a failable context like an if condition.
  3. B β€” UI text params take a localized message. Declare a helper like WelcomeText<localizes>(S:string):message and pass its result; there is no StringToMessage.
  4. B β€” RemoveWidget needs the same widget instance you added, so store it (e.g. in a [player]canvas map) when you call AddWidget.
  5. B β€” Each child sits in a canvas_slot with Anchors as 0..1 screen fractions and Offsets as pixel margins; the canvas has no position methods or events of its own.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Full rally HUD: laps + boosts + race position in one canvas

Sources

Lesson 33: Enums & Race Phases: State Machine Intro

Objectives

Model Lobby→Countdown→Racing→Finished as an enum and switch behavior per phase.

πŸ” Builds on: south-shores enum-with-data-pattern reference (anchor-beach)

🧩 Your capstone piece: race_phase enum driving the whole game loop

Quiz

  1. Which keyword defines a fixed set of named values in Verse?
    • A. class
    • B. enum
    • C. struct
    • D. module
  2. How do you access the value `Playing` from an enum named `game_state`?
    • A. game_state->Playing
    • B. game_state::Playing
    • C. game_state.Playing
    • D. game_state[Playing]
  3. Which operator compares two enum values for equality in Verse?
    • A. ==
    • B. =
    • C. ===
    • D. .equals
  4. How do you reassign a mutable `var CurrentState`?
    • A. CurrentState = newValue
    • B. set CurrentState = newValue
    • C. CurrentState := newValue
    • D. CurrentState += newValue
  5. Why must `GetPlayerUI[Player]` be called inside an `if` condition?
    • A. It is asynchronous
    • B. It is a <decides> (fallible) call that can fail
    • C. It returns a logic value
    • D. It requires a loop
Answer key
  1. B β€” `enum` declares an enumeration type with a fixed set of named enumerators.
  2. C β€” Enum values are accessed with a dot: `game_state.Playing`.
  3. B β€” Verse uses a single `=` for equality comparison, not `==`.
  4. B β€” Mutable variables are reassigned with the `set` keyword; a bare `=` on a var is an error.
  5. B β€” `GetPlayerUI` is `<decides>` β€” it can fail, so the `[]` call must be in a failure context like an `if`.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” race_phase enum driving the whole game loop

Sources

Lesson 34: MoveTo: The Swinging Gate Hazard

Objectives

Animate a creative_prop with MoveTo/TeleportTo β€” the first rung of the animation arc (β†’ ease β†’ prop_mover β†’ control rig).

πŸ” Builds on: south-shores spawn-prop lesson (the prop being animated)

🧩 Your capstone piece: Swinging gate hazard on the rope-bridge section

Quiz

  1. Why does the code use `Entity.GetComponent[keyframed_movement_component]` with square brackets inside an `if`, rather than calling it with round brackets?
    • A. Because looking up the component can fail (the entity might not have a mover), and square brackets signal a failable call the `if` can guard
    • B. Because square brackets are required for any call that returns a component
    • C. Because round brackets would make the component read-only
    • D. Because the mover must be retrieved before the transform can be read
  2. The delta sets `Translation.Forward := 500.0`. If you place the safe in a completely different spot in the vault and run the same component, where does it end up?
    • A. At world coordinate 500 on the Forward axis, regardless of where it started
    • B. 500 units forward from wherever it was placed, because the translation is relative
    • C. It fails, because the new position has no keyframe defined for it
    • D. Back at the vault origin, since deltas reset position first
  3. What is the practical effect of swapping `ease_in_out_cubic_bezier_easing_function{}` for `linear_easing_function{}` on the glide?
    • A. The safe moves a longer distance
    • B. The safe takes less total time to arrive
    • C. The safe moves at constant speed, feeling mechanical like a conveyor instead of weighty
    • D. The safe teleports instead of gliding
  4. Why does `OnBeginSimulation` call `(super:)OnBeginSimulation()` as its first line?
    • A. To restart the animation if it was already playing
    • B. To let the base `component` run its own startup before the subclass does its work
    • C. To register the component with the editor
    • D. It is required to make `@editable` knobs appear in the Details panel
  5. Which component do you add to an entity so it can be animated by playing a list of keyframe deltas?
    • A. transform_component
    • B. keyframed_movement_component
    • C. glide_to_target_component
    • D. simulation_component
Answer key
  1. A β€” Square brackets mark a failable expression: if no Keyframed Movement component was added, the lookup fails and the `if` simply skips. `GetLocalTransform()` uses round brackets precisely because it can never fail.
  2. B β€” A delta's translation is relative to the entity's current position, so the safe always glides 500 units forward from its start point. That is why one component works on any entity without hard-coded world coordinates.
  3. C β€” Easing only shapes the speed curve, not distance or duration. Linear gives constant speed (conveyor-like); ease-in-out starts slow, speeds up, and slows to a stop, which reads as weight.
  4. B β€” Calling the super first lets the base class complete its own setup before the subclass adds behavior. The `@editable` knobs and component registration are unrelated to this call.
  5. B β€” The keyframed movement component is the purpose-built mover: it plays keyframe deltas for an entity. `glide_to_target_component` is our custom script that finds the mover and presses Play; `transform_component` just holds where the entity sits.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” Swinging gate hazard on the rope-bridge section

Sources

Lesson 35: Scene Graph: Checkpoint as Entity + Component

Objectives

Wrap checkpoint logic in an entity with a Verse component instead of a bare script.

πŸ” Builds on: south-shores scene-graph fundamentals (steps 14-16)

🧩 Your capstone piece: checkpoint_component on a checkpoint entity

Quiz

  1. Why is GetComponent written with square brackets (GetComponent[mesh_component]) and placed inside an if:?
    • A. Because square brackets are required syntax for every method call in Verse
    • B. Because it returns an array of components that must be looped over
    • C. Because getting a component can fail β€” the entity might not have one of that kind β€” so it must be guarded
    • D. Because it modifies the entity, and modifications always need square brackets
  2. You want a custom component to run an ongoing loop that waits and repeats forever. Which lifetime method should hold that logic?
    • A. OnSimulate, because it is <suspends> and is where loops and waits live
    • B. OnBeginSimulation, because it runs first at startup
    • C. OnAddedToScene, because the component is freshly in the scene
    • D. OnEndSimulation, because the loop should keep going until shutdown
  3. When you build a new component in code, why must you write Entity := Entity (telling it which entity it belongs to)?
    • A. It is optional naming; Verse picks the nearest entity if you omit it
    • B. It tells the component to copy itself onto every child entity
    • C. It links the component to the simulation entity at the root
    • D. A component is born attached to exactly one entity for life β€” components cannot be moved between parents
  4. To make an entity's shape vanish temporarily without deleting it, the example calls Mesh.Disable(). What's the advantage of disabling over deleting?
    • A. Disabling frees more memory than deleting the entity
    • B. The mesh can be turned back on later with Enable(), so the thing can reappear
    • C. Deleting a mesh_component is not allowed in Verse
    • D. Disabling automatically removes the entity from the tree
  5. Fill in the blank: to define a component you can bolt onto an entity, you write my_component := class<____>(component):. What goes in the blank?
    • A. final_super
    • B. suspends
    • C. override
    • D. editable
Answer key
  1. C β€” Square brackets mark a verb that might fail (the <decides> effect); an entity may lack that component type. The if: safely skips when there's no match. Brackets are not a universal call syntax β€” round brackets mark calls that can't fail.
  2. A β€” OnSimulate is the <suspends> main-logic method built for loops, waits, and ongoing behavior. OnBeginSimulation is for instant must-finish-now setup, not for suspending loops.
  3. D β€” The lesson notes components cannot be moved between parents, so each is born attached to one entity for life β€” hence you must specify its entity at construction. Verse does not auto-pick or copy it across children.
  4. B β€” Disable()/Enable() flip a component off and on without destroying it, so the object can reappear later β€” the basis of the blink-on/off loop. Deleting would be permanent and removing it from the tree is unrelated.
  5. A β€” <final_super> is the required tag every time you make a component intended for an entity β€” it promises the class sits directly on top of component. <suspends> and <override> are effects/specifiers for methods, and @editable is an attribute for vars, not a class tag.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” checkpoint_component on a checkpoint entity

Sources

Lesson 36: Custom Component: Reusable Checkpoint Prefab

Objectives

Author a custom component, attach it, and save the checkpoint entity as a PREFAB other zones can drop in.

πŸ” Builds on: lesson 35 entity + CodewoodKit helpers

🧩 Your capstone piece: checkpoint prefab β€” exported to east-volcano/the-deeps modes

Quiz

  1. Why must a call like `Entity.GetComponent[light_component]` be wrapped in an `if` (or used with `or`)?
    • A. Because GetComponent is a failable lookup that may not find the component
    • B. Because light_component is a device
    • C. Because GetComponent runs asynchronously
    • D. Because Verse forbids square brackets outside loops
  2. What does a `light_component` depend on to know where it shines?
    • A. A trigger_device on the same entity
    • B. A transform_component on the entity
    • C. The creative_device's OnBegin
    • D. A material asset
  3. How do you reference a placed Scene Graph entity so Verse can act on it?
    • A. Call entity{} directly in OnBegin
    • B. Declare an @editable entity field on a creative_device and assign it in the Details panel
    • C. Use StringToMessage to name it
    • D. It happens automatically for every entity in the level
  4. Which method returns the direct child entities of an entity?
    • A. GetComponents()
    • B. GetLocalTransform()
    • C. GetEntities()
    • D. Enable()
  5. Why do the transform examples write `20.0` and `100.0` instead of `20` and `100`?
    • A. Style preference only
    • B. Verse does not auto-convert int to float, and translation vectors are float
    • C. Integers are not allowed in Scene Graph at all
    • D. Because SetLocalTransform rejects positive numbers
Answer key
  1. A β€” The `[]` form is a failable query β€” the entity might not have that component β€” so it must appear in a failure context like an `if`.
  2. B β€” The API notes that a transform_component on the entity positions the light.
  3. B β€” Like any placed thing, an entity must be held in an @editable field on a creative_device to be referenced from Verse.
  4. C β€” GetEntities() returns the []entity direct children; GetComponents() returns the []component on the entity itself.
  5. B β€” Vector translations are float components; Verse won't implicitly convert an int, so float literals are required.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” checkpoint prefab β€” exported to east-volcano/the-deeps modes

Sources

Lesson 37: Capstone: Barnaby's Jungle Mod-Rally

Objectives

Assemble every lesson into one playable rally mode: state machine, checkpoints, mod boxes, boosts, HUD, and persistence β€” launchable as a real island.

πŸ” Builds on: south-shores ShellHunt game-phase enum + SpawnProp helper; center-village custom-round-logic round loop; town matchmaking-portal launch

🧩 Your capstone piece: The full game β€” this IS the capstone assembly lesson

Quiz

  1. Final checkpoint: your submitted rally_game.verse compiles clean, but in playtest the race never leaves the Lobby phase. Which @editable wiring should you check FIRST?
    • A. LobbyGate β€” the player_counter_device: its CountSucceedsEvent is the only thing that ever starts the race.
    • B. FanfareSpeaker β€” without a speaker the announcer loop blocks forever.
    • C. ModStation β€” SpawnBox() must succeed before the countdown can run.
    • D. ReturnPortal β€” the race cannot start while the portal is disabled.
  2. Why does the capstone create one checkpoint_sensor object per trigger instead of subscribing HandleCheckpoint directly to every TriggeredEvent?
    • A. TriggeredEvent only delivers a ?agent payload β€” the sensor object carries WHICH route index fired and forwards both.
    • B. Subscribe can only be called once per device class.
    • C. Direct subscriptions are not allowed inside OnBegin.
    • D. Sensor objects make the triggers fire faster.
  3. What does gating HandleCheckpoint on Phase = race_phase.Racing protect against?
    • A. Checkpoint hits counting during the lobby, the countdown, or after the race has finished.
    • B. Two racers passing the same checkpoint in the same frame.
    • C. The compiler rejecting an unused enum value.
    • D. The trigger devices being disabled by the island settings.
  4. In the capstone, checkpoints Signal CheckpointPassedEvent and a loop in OnBegin Awaits it. What is the architectural win?
    • A. Checkpoint logic and HUD/fanfare reactions are decoupled β€” neither side knows the other exists, so each can change independently.
    • B. Signal/Await is the only way to update a text_block after it is created.
    • C. It makes the checkpoints run in parallel threads for performance.
    • D. Await batches multiple checkpoint hits into a single HUD update.
  5. Predict the HUD: a racer has just completed their final lap, so LapsOf[Racer] is 2 and LapCount is 2. UpdateHud computes ShownLap := Min(Laps + 1, LapCount). What lap label does the text_block show?
    • A. Lap 2/2 β€” Min clamps Laps + 1 (which would be 3) down to LapCount so the HUD never shows 'Lap 3/2'.
    • B. Lap 3/2 β€” Laps + 1 is displayed directly.
    • C. Lap 1/2 β€” the HUD resets to lap 1 when a lap completes.
    • D. Lap 0/2 β€” LapsOf is zeroed when the race finishes.
Answer key
  1. A β€” The entire flow is armed by LobbyGate.CountSucceedsEvent.Subscribe(OnGridFull). If the counter device is unwired (or its zone/target count is wrong in the editor), OnGridFull never fires and the phase machine stays in Lobby. The speaker, mod station, and portal are all downstream of the start.
  2. A β€” A trigger_device's TriggeredEvent is listenable(?agent): the handler learns who fired it, but not which gate it was. Binding an Index into a small class instance and subscribing that instance's method is the standard Verse pattern for passing extra context into event handlers.
  3. A β€” This is the ShellHunt phase-machine pattern imported from south-shores: every gameplay handler checks the phase first, so wandering riders cannot bank checkpoints before GO or after the winner is decided. One enum comparison eliminates a whole family of soft-locks.
  4. A β€” The event bus (from the verse-events-custom lesson) means HandleCheckpoint never touches UI or audio, and the announcer task never touches triggers. In a 37-lesson game that decoupling is what keeps every new reaction β€” stats, replays, commentary β€” a subscriber away instead of a rewrite.
  5. A β€” Laps + 1 gives the lap the racer is 'on', but after the final lap that arithmetic overshoots to 3. Min(Laps + 1, LapCount) clamps the displayed lap at LapCount, so the winner's HUD reads 'Lap 2/2' instead of the nonsensical 'Lap 3/2'.

Recap

One step closer to Barnaby's Jungle Mod-Rally β€” The full game β€” this IS the capstone assembly lesson

Sources

Generated by Verse Island on 2026-07-04.