Jelly vs Tower

Level: Advanced 60–90 min

Concepts: Business LogicDesign PatternsEdge CasesValidation

Solutions: C# | TypeScript | Python


Build a tower defense combat system inspired by JellyDefense. Towers attack incoming jellies based on color matching and level-based damage tables.

Requirements

Entities

Both Jellies and Towers have:

  • A unique identifier
  • A color type: Blue, Red, or BlueRed
  • A health value
  • Alive/dead status (dead when health ≤ 0)

Towers additionally have a level (1–4).

Damage Rules

Damage dealt depends on the tower type, tower level, and jelly color:

Tower Typevs Blue Jellyvs Red Jelly
Blue TowerL1: 2–5, L2: 5–9, L3: 9–12, L4: 12–15L1: 0, L2: 1, L3: 2, L4: 3
Red TowerL1: 0, L2: 1, L3: 2, L4: 3L1: 2–5, L2: 5–9, L3: 9–12, L4: 12–15
BlueRed TowerL1: 2, L2: 2–4, L3: 4–6, L4: 6–8L1: 2, L2: 2–4, L3: 4–6, L4: 6–8
  • Damage ranges are random within the specified bounds (accept an injectable random source)
  • A BlueRed Jelly takes damage from both the Blue and Red columns (use the higher value)

Combat Flow

Each round:

  1. Each tower attacks one jelly (closest or first alive)
  2. Apply damage based on the rules table
  3. Remove dead jellies
  4. Report combat log (which tower hit which jelly for how much damage)

Test Cases

TowerLevelJelly ColorMin DamageMax Damage
Blue1Blue25
Blue1Red00
Red3Red912
Red2Blue11
BlueRed4Blue68
BlueRed4Red68

Additional cases:

  • Jelly dies when health reaches 0
  • Dead jellies cannot be attacked
  • Tower attacks do nothing if no jellies remain
  • BlueRed jelly takes the higher of Blue/Red damage columns

Bonus

  • Add tower targeting priority (closest, weakest, strongest)
  • Add jelly movement — jellies advance each round, towers only attack jellies in range
  • Add tower upgrade mechanics — towers can be upgraded mid-game
  • Track kill counts per tower

Hint

Start with a single tower attacking a single jelly with fixed damage. Get the health/death logic working first. Then introduce the damage table lookup. Randomized damage ranges and multiple entities come last.

Reference Walkthrough

Full C#, TypeScript, and Python implementations live at tddbuddy-reference-katas/jelly-vs-tower with the same twenty-five scenarios across all three languages, fluent TowerBuilder and JellyBuilder, an injectable RandomSource for deterministic damage, and an Arena that orchestrates combat rounds.

This kata ships in middle gear — a single commit per language with the full domain design. See the repo’s Gears section for why that’s a deliberate teaching choice.


  • Examples Pin Intent. Properties Pin the Invariants.
    Example-based tests anchor scenarios in the team's vocabulary. Property-based tests anchor invariants across the input space. The agent needs both axes, and most suites only carry one.
  • 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.