Mars Rover
Level: Intermediate 30–60 minConcepts: Design
Solutions: C# | TypeScript | Python
Develop an API that moves a rover around a grid on Mars.
- You are given the initial starting point(x,y) of a rover and the direction (N,S,E,W) it is facing.
- The rover receives a string of commands. Implement commands that:
- Move the rover forward(f)
- Move the rover backward(b)
- Turn the rover left(l)
- Turn the rover right(r)
- Implement wrapping from one edge or the grid to another - Planets are spheres after all.
Hint
Your constructor should look like: MarsRover(location, direction, gridSize). E.g var rover = new MarsRover([0,0],‘e’,[50,50]);
Example
The rover is on a 100x100 grid at location (0, 0) and facing SOUTH. The rover is given the commands “fflff” and should end up at (2,2).
Bonus
Implement obstacle detection before each move to a new square. If a given sequence of commands encounters an obstacle, move the rover up to the last possible point and reports the obstacle. You will need to amend your code to take in an array of obstacles.
Reference Walkthrough
Reference implementations in C#, TypeScript, and Python live at tddbuddy-reference-katas/mars-rover. This is an F2 (light builder) kata: one primary entity (Rover), three value enums (Direction, Command, MovementStatus), one domain exception (UnknownCommandException), and two small test-folder builders — RoverBuilder (.at().facing().onGrid().withObstacleAt()) and CommandBuilder (.forward().left().build() → "FL"). Obstacle blocking is modelled as a result state on the rover (status, lastObstacle), not an exception — the kata brief asks the rover to report the obstacle, which it does as a first-class state rather than a thrown error.
Scope note — pure domain only. The reference covers position, heading, forward/backward movement, rotation, grid wrapping, and obstacle detection. A renderer (ASCII grid print), a CLI loop, alternative command formats (whitespace, lowercase, numeric repeats like 3F), and multi-rover worlds are all out of scope and listed as stretch goals in the repo README. Those responsibilities introduce collaborators (renderers, input parsers, shared world state) — which is F3 territory, not F2.
- C# (.NET 8, xUnit, FluentAssertions 6.12.0) — walkthrough
- TypeScript (Node 20, Vitest 1.6, TS 5 strict) — walkthrough
- Python (3.11, pytest) — walkthrough
This kata ships in Agent Full-Bake mode at middle gear, the F2 (light builder) tier. See the repo’s Gears section for why middle gear is the deliberate choice.
Related reading
- The Test Pyramid Was an Economic Argument
The test pyramid was not a quality law. It was a cost structure: unit tests were cheap, integration tests were expensive, so you wrote many of the first and few of the second. Agents collapsed the cost of writing tests at every level, and the cheapest test that still tells the truth is the one that pins a seam the agent cannot fake. - Agents Amplify Whatever Vocabulary They Find
Agents do not bring vocabulary to your codebase. They mirror what's already there. Strong vocabulary gets agent contributions that read like the team. Weak vocabulary gets faster mediocrity. The work you did for craft reasons just became leverage. - The Hidden Output of TDD Was Never Code
The visible artifact of TDD is a passing test suite. The actual artifact, the one that compounded value over the life of the codebase, was the vocabulary the team built while writing it. The dictionary, not the regression net.