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.
179 lines
8.6 KiB
Markdown
179 lines
8.6 KiB
Markdown
# 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.*
|
||
**
|