🤖 Virtual Lab: Robot Arena
In these two labs you assemble a small C++ program from a palette of instruction tiles, then watch a deterministic interpreter run it as a robot’s per-tick control loop on a grid. A pseudo-compiler checks your program before it can run, emitting g++-style diagnostics for unbalanced braces or empty blocks, so a clean compile is the price of admission. The goal each time is to locate the enemy, close in, and fire before you run out of actions or energy.
The two labs are a deliberate sequence. The first isolates control flow. The second keeps that exact structure and adds variables and mutable state, plus an enemy that no longer holds still, so you have to reason about a value that changes over time and a target that reacts to what you do.
Lab 1: Control Flow
Section titled “Lab 1: Control Flow”The first arena is about ordering and shaping the flow of execution. Every win comes from sequencing a few actions and wrapping them in the right block, with nothing to track but position, heading, and two budgets.
| Language element | Where it shows up |
|---|---|
| Sequencing | Statements run top to bottom as the robot’s tick() loop. |
if (conditional) | if (enemy_visible()) runs its body only when the last scan() saw the enemy. |
for (counted loop) | for (int i = 0; i < 3; i++) repeats its body a fixed number of times. |
while (condition loop) | while (distance() > 3) repeats until a sensor condition stops holding. |
| Block scope and braces | Every { must be matched by a }; an empty block is a compile error. |
| Side effects and cost | Each action spends from an action limit and an energy budget, so wasted statements have a price. |
The key insight the lab pushes you toward is that a program hard-wired to one approach fails, because the start position and facing are random every run. The robust answer is a loop: scan to locate, turn to face, move to close the gap, then fire.
Robot Arena: Control Flow
Lab 2: Variables and a Moving Enemy
Section titled “Lab 2: Variables and a Moving Enemy”The second arena reuses the same instruction set and narrative, then introduces the one idea the first lab cannot express: a variable your program reads and writes as it runs. You now carry ammo, and the numbers are deliberately tight. The enemy must be hit three times to destroy, but your robot stores only two rounds before it has to reload(). Two shots are never enough on their own, so somewhere in the fight you have to notice you are empty and reload. The only way to know that is to read the variable with if (ammo() == 0). A program that ignores ammo, like any Lab 1 solution, lands at most two hits and always loses.
On top of that, the enemy is now skittish: as you approach, it sometimes darts a cell away at the edge of your range, though once you have closed right in it can no longer escape. So you close the gap, pin it, and then fire and reload until its three hit points reach zero.
| Language element | Where it shows up |
|---|---|
| Mutable state (a variable over time) | ammo starts at 2, drops by one on each fire(), and resets to 2 on reload(). |
| A constraint that forces the read | The enemy needs 3 hits but you hold only 2 rounds, so you cannot win without checking ammo and reloading. |
| Reading a variable in a condition | if (ammo() == 0) branches on the variable’s current value to decide when to reload. |
| State changing across iterations | Inside the fire loop, ammo and the enemy’s remaining hit points both change every pass. |
| Stale vs fresh data | The cached distance() is only as current as your last scan(); the dodging enemy makes re-scanning matter. |
| Everything from Lab 1 | The same control-flow elements still apply; the variable sits on top of them. |
Because the enemy reacts only when you move, turning, firing, and reloading are “free time” it cannot dodge. The strong solution closes all the way in where the enemy is pinned, then loops: reload when empty, aim, fire, and re-scan, repeating until all three hit points are gone.
Robot Arena: Variables & a Moving Enemy
Wrap-up
Section titled “Wrap-up”Across the two labs you have built working programs out of the same primitives that structure all C++ code: sequencing, conditionals, counted and conditional loops, block scope, and a mutable variable that carries state from one step to the next. The progression mirrors how these ideas are normally taught. First you control which statements run and how often, then you add a value that those statements change and read back, which is the foundation of every algorithm that has to remember anything.
In Lab 1, why does a program with a fixed sequence of moves (rather than a loop guarded by a sensor) usually fail?
In Lab 2, what is the core new concept that 'ammo' introduces compared with Lab 1?
In Lab 2 the enemy takes three hits but your robot stores only two rounds. What does this force every winning program to do?
© 2026 Derek Molloy, Dublin City University. All rights reserved.