Files
institution/Wiki/contraband/Tunnels.md
T
flan e96ac23949 Move AI attribution to a single NOTICE file
Per the updated project policy, AI/Claude attribution lives in exactly one NOTICE file per repo and
nowhere else -- removed it from the About description, README, wiki, and roadmap.
2026-07-16 01:30:09 +00:00

179 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tunnels
*The Prison-Architect dig: a disposed pawn goes down, not through — under the ground and everything
built on it, out past the last wall you were relying on.*
A locked door stops a prisoner who wants to walk out. It does nothing at all about a prisoner who
digs. This is the escape that ignores your perimeter, because it does not cross it — it goes beneath
it. It is slow, it is quiet, and it works for pawns who would never join a mood-driven riot.
## The crude pick
The dig needs a tool. `CB_DiggingTool` is a crude pick, filed off the cell's own furniture exactly
the way a shiv is (`AcquireWorker_Improvise` — same disposition gate, same damage-to-furniture
tell; see [Improvised Weapons](Improvised-Weapons.md)). Where the shiv is a weapon, this is a *way
out*: it carries no combat stats and is never equipped.
| Stat | Value |
|---|---|
| Description | *"Useless as a weapon and useless above ground — but pointed downward, patiently, it is a way out that no lock and no guard can see."* |
| Max HP | 60 |
| Mass | 1.2 kg |
| `concealability` | **0.5** |
| `hideIn` | `InCell` only (too bulky to ride on a body) |
| `acquireWorker` | `AcquireWorker_Improvise` |
| `escapeWorker` | `EscapeTunnelWorker` |
| Deterioration | 2.0 |
Because it hides `InCell` only, a warden turning over the *room* can find the pick itself — and, far
more easily, the hole it is digging.
## A second secret riding on the first
A tunnel is *"the third thing a contraband item can be, after 'made' and 'used in a break': a thing
you dig your way OUT with, quietly, over days."* It is deliberately **not a Job**. There is no
supervised task a warden could walk in on and interrupt — only a secret that grows and a wall that
eventually gives. Progress is driven from `MapComponent_Contraband`'s poll (`TickTunnels`), the same
250-tick heartbeat that makes contraband, so *the same search that finds a shiv can find the tunnel*.
The pick must first be **made** (or smuggled). Only once it is finished (`Ready`) does the dig begin,
as a second, longer secret carried on the same `ConcealedItem` (`escapeProgress`, `escapeWall`).
## Who digs
`EscapeTunnelWorker.WouldDig` gates on three things:
1. **Humanlike and held** — prisoner, slave, or ward patient (`IsHeld`, via Core's secured context).
2. **The disposition to dig for weeks:**
```
Propensity.Would(holder, 0.08, SaltTunnel)
```
Base chance **0.08** — deliberately below the shiv's 0.10. *"Fewer pawns will dig for weeks than
will palm a shiv."* Seeded per pawn, so it is a fixed fact about them.
3. **A viable plan exists** — there has to be somewhere to surface (see below).
This is the entire reason tunnels live in Contraband and not in a prisoner-only escape mod:
> It works for prisoners **and ward patients** alike. Prisoner Realism's escapes are for "mood
> prisoners" mid-break bashing a door, and a committed ward patient is never that pawn. A patient
> with a filed-down pick and the disposition to use it can still, slowly, dig out — and nothing else
> in the ecosystem lets them.
## Planning the dig: aim for the wilderness
The target is **not** the cell wall. *"You do not go through the wall, you go under it."* `TryPlan`
finds the **nearest wilderness** — the first standable cell, scanning radially outward from the
holder up to **60 tiles** (`MaxSearchRadius`), whose room *touches the map edge* and is not the room
they are held in.
Two consequences fall straight out of that:
- **Depth is your defence, and a single wall is not.** A tunnel from a deep bunker is a long dig; a
tunnel from a shack against the map edge is a short one. Wrapping one more wall around a cell does
almost nothing — the dig already ignores intervening walls entirely.
- **A fully enclosed, map-locked base with no reachable edge has nowhere to surface.** `TryPlan`
fails, `ProgressPerCheck` returns 0, and the tunnel **stalls** — progress is kept, not lost. Seal
the map and the shaft simply waits.
### How long
Dig time scales with how deep the cell sits:
```
requiredDays = clamp(distanceToWilderness / 6, 3, 15) // CellsPerDay = 6
progressPerPoll = 250 / (requiredDays × 60000) × Rand.Range(0.75, 1.25)
```
| | Days |
|---|---|
| Minimum (shallow cell near the edge) | **3** |
| Maximum (deep bunker) | **15** |
| Per day of digging | ~6 cells of depth |
The floor of 3 days keeps even the shortest tunnel a *real threat window* you have time to catch; the
ceiling of 15 keeps the deepest from being effectively forever.
## The tell: spoil
A dig has to go somewhere, and the dirt is where you notice it. Each dig tick, with a 50% seeded
chance (`OnDigTick`), the worker drops one tile of `Filth_Dirt` at the holder's position:
> A dirt floor swallows it; a paved cell shows it — exactly where a player might notice.
It is cheap and occasional on purpose: enough that a paved cell slowly accumulates a suspicious mess,
not so much that it spams filth or litters a clean cell every tick. If you floor your cells, spoil is
a genuine visual cue that someone is digging.
## Finding a tunnel in a search
A tunnel is *"a second, far less hideable secret."* The pick has `concealability` 0.5, but the
**shaft** gives itself away in proportion to how far along it is. When a warden search reaches the
`InCell` site, `ExtraDiscoverChance` is added on top of the tool's normal find chance:
```
extraChance = clamp01(escapeProgress) × 0.4 // up to +0.40 at a nearly-finished tunnel
```
So a routine cell toss that finds a shiv can also catch a dig in progress — *"the same guard patrol
that finds a shiv finds the hole"* — and the deeper the shaft, the harder it is to miss. A foiled
dig is logged the same as one that ran: on discovery, `CriminalRecord.escapeAttempts` is
incremented, which raises this pawn's future search priority sharply (a known tunneller is the
prisoner a warden checks first — see [Warden Search](Warden-Search.md)). The full find math is on the
[Warden Search](Warden-Search.md) page.
## Breakout
When `escapeProgress` reaches 1, `OnBreakout` fires:
1. **Re-plan the exit** so it is correct even if the base changed during the weeks of digging.
2. **Breach the outer wall or fence** the tunnel comes up beside (`LastContainmentOnLine` — the
*outermost* impassable edifice or fence between the cell and the surfacing point, walking inward
from the exit). It is destroyed with `KillFinalize` — a visible hole the colony must repair, and
proof of how they got out. An open perimeter needs no breach.
3. **Record the attempt** (`escapeAttempts++`) — it happened whether or not they get clear of the
map.
4. **Surface beyond the perimeter.** They dug all the way out, so they emerge *outside*, not in the
yard: the pawn is teleported to the exit cell, with a little spoil dirt to mark where they came
up.
5. **Hand off to vanilla** (`PrisonBreakUtility.StartPrisonBreak`). Now that they are loose and
outside, the base game's prison-break flow — and anything layered on it, e.g. **Prisoner
Realism** — takes it from there. A pawn already outside who no longer qualifies as an in-prison
escapee simply flees on their own; the breach and the emergence are the real outcome regardless.
The player gets one message: *"{pawn} has tunnelled out under the perimeter and escaped."* The tunnel
and the pick are spent together — the `ConcealedItem` is removed.
## How to defend against it
| Defence | Effect |
|---|---|
| **Floor the cells** | spoil dirt becomes visible; you can *see* a dig |
| **Search known offenders** | a logged escape attempt is the heaviest single term in search priority |
| **Deny the pick's raw material** | no workable furniture, no pick — same starve as the shiv |
| **Depth** | a deeper cell is a longer dig and a wider window to catch it |
| **Seal the map** | no reachable edge means the tunnel stalls indefinitely |
Note what does **not** help much: adding perimeter walls. The dig goes under them and only breaches
the *last* one on the way out.
## Quick reference
| Constant | Value | Meaning |
|---|---|---|
| Dig base chance | 0.08 | before nature × nurture; seeded per pawn |
| Wilderness search radius | 60 tiles | how far out it looks for a surfacing point |
| Cells per day | 6 | dig speed vs. cell depth |
| Min / max dig time | 3 / 15 days | clamps on `distance / 6` |
| Spoil chance per dig tick | 50% | one tile of `Filth_Dirt` |
| Extra find chance | up to +0.40 | scales with `escapeProgress` |
| Pick `concealability` | 0.5 | `InCell` only |
| On discovery / breakout | `escapeAttempts++` | logged either way |
---
*Part of the **Institution** suite — Core · Contraband · Justice · Gangs, alongside Foul Play and
Ward. Each stands alone; together they interlock.*
**