Count Matching: How Many Racers Passed?
In this lesson you'll learn to
- βCount array elements matching a condition (racers past checkpoint N).
Count array elements matching a condition (racers past checkpoint N).
π Reference & full walkthrough: Count Matching: How Many Racers Passed?
π§© Your capstone piece: Racers-remaining and checkpoint-progress counters
Barnaby the bear has a clipboard problem. Six dirtbikes are tearing through Codewood Grove, and every few seconds someone on the sidelines yells "how many racers made it past the rope bridge?!" Counting by paw takes too long. Counting with a for loop and an if takes one blink β and that is exactly the skill this lesson locks in: walk an array, test each element against a condition, and add 1 every time the test passes.
If you finished the sum-an-array lesson, this will feel familiar. Summing says "add the value to the total." Counting says "add 1 to the total β but only when the element passes a test." Same loop skeleton, one extra if. That tiny difference powers every "racers remaining", "players ready", and "checkpoints cleared" counter you will ever build.
What you will build
A checkpoint_progress_device for Barnaby's Jungle Mod-Rally β the north-jungle capstone. When a trigger_device at a checkpoint fires, the device counts two things from plain []int arrays and flashes them on every screen with a hud_message_device:
- Checkpoint progress β how many racers have passed checkpoint 3 (Zipline Run) or beyond.
- Racers remaining β how many racers have not yet finished all their laps.
These are the exact "racers-remaining and checkpoint-progress counters" the Mod-Rally race manager reads every time a checkpoint fires, so the code you write here drops straight into the capstone.
Walkthrough
The counting pattern
Every count-matching counter has four beats:
var Count : int = 0β start at zero.for (Value : MyArray)β visit every element.if (Value >= Threshold):β the condition. Only elements that pass get counted.set Count += 1β add one (not the value β this is a headcount, not a treasure tally).
Here is the complete device. Wire the two @editable device references in the UEFN Details panel, drop it on your island, and it compiles and runs as-is.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Native }
# Localisation helper β HUD messages must be `message`, not raw string.
RallyMessage<localizes>(S : string) : message = "{S}"
checkpoint_progress_device := class(creative_device):
# ββ Editable device references ββββββββββββββββββββββββββββββββββββββββ
# Wire this to the trigger_device sensor at the checkpoint.
@editable
CheckpointTrigger : trigger_device = trigger_device{}
# HUD message device set to "All Players" in its properties.
@editable
ProgressHUD : hud_message_device = hud_message_device{}
# ββ Race data (the capstone updates these as racers ride) βββββββββββββ
# Highest checkpoint each racer has passed this lap. Index 0 = racer 1.
@editable
RacerCheckpoints : []int = array{3, 1, 4, 2, 4, 0}
# Laps completed per racer β same racer order as above.
@editable
RacerLaps : []int = array{1, 0, 2, 1, 2, 0}
# The rally is a 3-lap race by default.
@editable
TotalLaps : int = 3
# Which checkpoint we are reporting progress for (3 = Zipline Run).
@editable
ReportCheckpoint : int = 3
# ββ The reusable counter ββββββββββββββββββββββββββββββββββββββββββββββ
# Counts how many values in Values are at least Threshold.
CountAtLeast(Values : []int, Threshold : int) : int =
var Count : int = 0
for (Value : Values):
if (Value >= Threshold):
set Count += 1
Count
# ββ Lifecycle βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
OnBegin<override>()<suspends> : void =
# When the checkpoint sensor fires, refresh the counters.
CheckpointTrigger.TriggeredEvent.Subscribe(OnCheckpointPassed)
# 0.0 keeps the message on screen until we replace it.
ProgressHUD.SetDisplayTime(0.0)
# ββ Event handler β TriggeredEvent sends ?agent βββββββββββββββββββββββ
OnCheckpointPassed(MaybeAgent : ?agent) : void =
# Counter 1: racers at or past the report checkpoint.
PastCheckpoint : int = CountAtLeast(RacerCheckpoints, ReportCheckpoint)
# Counter 2: racers remaining β laps still BELOW the total.
var StillRacing : int = 0
for (Laps : RacerLaps):
if (Laps < TotalLaps):
set StillRacing += 1
ProgressHUD.Show(RallyMessage("{PastCheckpoint} past checkpoint {ReportCheckpoint} - {StillRacing} racers still in the rally!"))
Line-by-line explanation
| Lines | What's happening |
|---|---|
RallyMessage<localizes> |
hud_message_device.Show takes a message, so we wrap our string in a <localizes> function β the same helper pattern from the sum-an-array lesson. |
RacerCheckpoints : []int |
One slot per racer, holding the highest checkpoint passed. With the sample data, racers 0, 2 and 4 have reached checkpoint 3+. |
CountAtLeast(Values, Threshold) |
The counter as a function β write the loop once, reuse it for any array and any threshold. Its last expression, Count, is the return value. |
if (Value >= Threshold): |
The condition. >= is a failable comparison β the set Count += 1 line only runs when it succeeds. |
set Count += 1 |
Add 1 per match. Compare with summing, where you write set Total += Value. |
TriggeredEvent.Subscribe(OnCheckpointPassed) |
trigger_device.TriggeredEvent is listenable(?agent), so the handler takes ?agent. |
if (Laps < TotalLaps): |
The racers-remaining condition inline β sometimes the count is a one-off and does not need its own function. |
ProgressHUD.Show(...) |
Broadcasts both counters to every player in one message. |
With the sample arrays: CountAtLeast(RacerCheckpoints, 3) returns 3 (the values 3, 4 and 4 pass the test), and the remaining-loop returns 6 β nobody has banked all 3 laps yet, so every racer is still in the rally. Run it, tweak the arrays in the Details panel, and watch the numbers move. That instant feedback is the fastest way to make the pattern stick.
Common patterns
Pattern 1 β Count exact matches with =
Sometimes you want "racers on exactly lap 2", not "lap 2 or more". In a condition, Verse compares equality with a single = (it is a failable check, not an assignment):
# Counts racers whose lap counter is exactly TargetLap.
CountOnLap(LapsPerRacer : []int, TargetLap : int) : int =
var Count : int = 0
for (Laps : LapsPerRacer):
if (Laps = TargetLap):
set Count += 1
Count
Handy for a "3 riders battling on lap 2!" commentary line. Use <> if you ever need "not equal".
Pattern 2 β Compound conditions with and
Conditions can stack. This counter finds racers closing in on the finish: on their final lap and already past the halfway checkpoint:
# Racers on their last lap who have passed the halfway checkpoint.
CountClosingIn(LapsPerRacer : []int, Checkpoints : []int, FinalLap : int, HalfwayPoint : int) : int =
var Count : int = 0
for (Index -> Laps : LapsPerRacer):
if (Laps >= FinalLap - 1 and Checkpoints[Index] >= HalfwayPoint):
set Count += 1
Count
The Index -> Laps form gives you the position too, so you can look up the same racer in a second array β both conditions must succeed before the count bumps. (Array indexing Checkpoints[Index] is failable, which is fine: it just becomes part of the condition.)
Where this goes next
- Next lesson β filter-an-array: counting tells you how many passed the test; filtering hands you the elements themselves. Same loop, but you build a new array instead of bumping a counter.
- The capstone β Barnaby's Jungle Mod-Rally: the race manager imports exactly this piece.
CountAtLeastdrives the checkpoint-progress HUD line after everyCheckpointPassedEvent, and the racers-remaining loop (withlaps < TotalLaps) decides when the rally flips itsrace_phasestate machine to Finished. When you reach the maps lesson, the[]intarrays upgrade to[player]intmaps β but the counting condition you wrote today stays word-for-word the same.
Keep going β free
You've read the intro. The rest of this lesson is free for members. Sign in to continue and track your progress.
Sign in free to continue this lessonSources
/guides/count-matchingBiloxi Studios original lesson
Add this lesson to your free study plan.
π§ The Keeperβs log
Quest complete? Chart your next heading from the π» North Jungle expedition.
β΅ Take me there