# td · the tower defence law

**Lars Rocha's law** · `sitoolz/td.py` ↔ `js/td.js` · fixtures `fixtures/td.json` (written by the Python reference,
423 games and 52 table rows) · tools `tools/td-balance.py`, `tools/td-tune.py`

> A tower does not stand at a point on a map. It covers a stretch of the path, `[a, b]` in metres along the route the
> enemies walk. Given a map, a set of towers and a wave table, the run is fixed.

## The move

The same one the square-shell addressing makes for terrain: **index a two-dimensional problem onto a line.** A tower
game played on a plane needs geometry, collision and a frame rate. Played on a line it needs none of them. The
consequences are the point:

- **Exact.** A tower covers a stretch or it does not. No near misses, no "did that shell connect".
- **Deterministic.** No clock, no frame rate, no randomness not drawn from the law. The same recipe gives the same
  result on any machine, in either language, for ever.
- **Measurable.** A whole five-wave game is a few thousand integer ticks, about a millisecond. Ten thousand games
  take seconds, so the balance can be *computed* rather than felt.

That last one is why this exists. A tower game lives or dies on its balance, and balance is the one thing that cannot
be eyeballed.

## The arithmetic

**Scaling.** Health compounds at 1.10 a wave. Armour compounds at 0.6 of that rate, so an early damage type never
becomes worthless. Bounty grows as the square root of health, so a player cannot out-earn the curve by surviving.

**Damage.** A tower in reach spreads its damage per second over whatever it can see, nearest the keep first, up to
`1 + splash` targets. Armour divides: `damage × 1/(1 + armour × 0.12)`, after `pierce` and any mast's `strip` are
taken off it.

**Marks.** Two and three are numbers; four changes behaviour. The silo leaves ground burning, the rail ignores armour
entirely, the scatter widens, the mast strips armour from what it slows.

**A tick** is 0.1 s. Everything steps on it, in a fixed order, which is what lets the twins agree to the last decimal.

## What the model found

Every number in the tables has a measurement behind it, not a preference.

| finding | what it was | what it is |
| --- | --- | --- |
| the upgrade ladder was a trap | 0.8 / 1.3 / 2.1 → upgrading won 0% of openings against building's 42% | 0.5 / 0.8 / 2.1, both at 42% |
| difficulty was partly poverty | ace started on 280 and no opening won by any policy | one purse of 400 for all three |
| the opening, by difficulty | — | rookie 83%, captain 67%, ace 22% |

A sweep of 27 price ladders produced the first row; a sweep of six purses produced the second. Neither needed a
person to play anything.

## Known limits

- **It is a model of the game, not the game.** Tune here, port what it finds, then check the ported numbers against
  the live version rather than assuming they transfer.
- **The spending policies are deliberately simple**: buy the cheapest upgrade repeatedly, or add a tower into the
  widest uncovered stretch. They bound what a reasonable player could do; they do not play well.
- **One path shape.** The law describes a route of a given length; which route, and how it doubles back, is the
  caller's business.
- **No terrain yet.** Height, sightlines and dead ground are what Wander brings to this genre and the model does not
  know about them.
