Add a second intake: six more agents, with portraits

Written for the group that actually plays. Three postings and three trades
again, and none of the six repeats a posting or a trade already on the sheet,
so the roster now covers sixteen different jobs and no two players can pick the
same character by accident.

  Gareth Pollard      Night Warden          Field Officer
  Dominic Ashcroft    Anchor Officer        Senior Field Officer
  Neil Braithwaite    Pathology Officer     Field Officer
  Kate Renshaw        Interview Officer     Senior Field Officer
  Danny Sharrock      Construction Worker   Probationary
  Colin Ferriby       IT Specialist         Probationary

Each also gets a before-the-department entry, because without one they cannot
play OPEN DAY — the prologue builds its civilians off the BEFORE table, and the
build throws on a roster agent that has no entry in it. Two of the six were
already trades, so their civilian self is the same job with none of the kit.

Two guards had to be corrected rather than satisfied, both for the same reason:
they had encoded an accident of the roster being exactly ten.

  - "the ten cover all ten trades exactly once" cannot survive a sixteenth
    agent. The property that actually matters is that no trade is missing, so
    that is what it asserts now.
  - "the roster should be half trades" would mean picking characters to satisfy
    a ratio. It now asserts both halves are present and neither dwarfs the
    other, and separately that no job appears twice — which is the check with
    real teeth, and it passes.

The portrait pass caught an arithmetic slip of mine: Sharrock came back looking
early forties against a sheet that said 35, and his biography says twenty years
on sites, which would have him starting at fifteen. He is 42.

Verified in Foundry: 36 pregens in the pack, all twelve import, sheets render
with their portraits.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
slaguru666
2026-08-12 17:19:58 +01:00
co-authored by Claude Opus 5
parent f185c92088
commit f576c7977d
46 changed files with 236 additions and 109 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.614122 175327000 Recovering log #3
2026/08/12-17:01:00.614259 175327000 Level-0 table #5: started
2026/08/12-17:01:00.614456 175327000 Level-0 table #5: 4591 bytes OK
2026/08/12-17:01:00.614819 175327000 Delete type=0 #3
2026/08/12-17:01:00.614874 175327000 Delete type=3 #2
2026/08/12-17:19:00.088570 171de3000 Recovering log #3
2026/08/12-17:19:00.088713 171de3000 Level-0 table #5: started
2026/08/12-17:19:00.088860 171de3000 Level-0 table #5: 4591 bytes OK
2026/08/12-17:19:00.089133 171de3000 Delete type=0 #3
2026/08/12-17:19:00.089168 171de3000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.626690 174043000 Delete type=3 #1
2026/08/12-17:18:28.603922 172807000 Delete type=3 #1
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.636996 174b1b000 Recovering log #3
2026/08/12-17:01:00.637306 174b1b000 Level-0 table #5: started
2026/08/12-17:01:00.637497 174b1b000 Level-0 table #5: 4129 bytes OK
2026/08/12-17:01:00.637855 174b1b000 Delete type=0 #3
2026/08/12-17:01:00.637904 174b1b000 Delete type=3 #2
2026/08/12-17:19:00.109401 172dfb000 Recovering log #3
2026/08/12-17:19:00.109721 172dfb000 Level-0 table #5: started
2026/08/12-17:19:00.109829 172dfb000 Level-0 table #5: 4129 bytes OK
2026/08/12-17:19:00.110053 172dfb000 Delete type=0 #3
2026/08/12-17:19:00.110082 172dfb000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.686108 17302b000 Delete type=3 #1
2026/08/12-17:18:28.677543 173013000 Delete type=3 #1
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.616027 17430f000 Recovering log #3
2026/08/12-17:01:00.616428 17430f000 Level-0 table #5: started
2026/08/12-17:01:00.616905 17430f000 Level-0 table #5: 31614 bytes OK
2026/08/12-17:01:00.617273 17430f000 Delete type=0 #3
2026/08/12-17:01:00.617332 17430f000 Delete type=3 #2
2026/08/12-17:19:00.089865 172dfb000 Recovering log #3
2026/08/12-17:19:00.090418 172dfb000 Level-0 table #5: started
2026/08/12-17:19:00.090766 172dfb000 Level-0 table #5: 31614 bytes OK
2026/08/12-17:19:00.091075 172dfb000 Delete type=0 #3
2026/08/12-17:19:00.091125 172dfb000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.629106 17302b000 Delete type=3 #1
2026/08/12-17:18:28.606186 172807000 Delete type=3 #1
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.599970 17430f000 Recovering log #3
2026/08/12-17:01:00.601549 17430f000 Level-0 table #5: started
2026/08/12-17:01:00.603342 17430f000 Level-0 table #5: 225945 bytes OK
2026/08/12-17:01:00.603666 17430f000 Delete type=0 #3
2026/08/12-17:01:00.603818 17430f000 Delete type=3 #2
2026/08/12-17:19:00.074858 172dfb000 Recovering log #3
2026/08/12-17:19:00.076687 172dfb000 Level-0 table #5: started
2026/08/12-17:19:00.078405 172dfb000 Level-0 table #5: 225945 bytes OK
2026/08/12-17:19:00.078758 172dfb000 Delete type=0 #3
2026/08/12-17:19:00.078869 172dfb000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.656732 173837000 Delete type=3 #1
2026/08/12-17:18:28.644950 173013000 Delete type=3 #1
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.610773 173b03000 Recovering log #3
2026/08/12-17:01:00.610856 173b03000 Level-0 table #5: started
2026/08/12-17:01:00.611014 173b03000 Level-0 table #5: 3295 bytes OK
2026/08/12-17:01:00.611276 173b03000 Delete type=0 #3
2026/08/12-17:01:00.611326 173b03000 Delete type=3 #2
2026/08/12-17:19:00.085539 171de3000 Recovering log #3
2026/08/12-17:19:00.085669 171de3000 Level-0 table #5: started
2026/08/12-17:19:00.085805 171de3000 Level-0 table #5: 3295 bytes OK
2026/08/12-17:19:00.086064 171de3000 Delete type=0 #3
2026/08/12-17:19:00.086105 171de3000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.680967 174043000 Delete type=3 #1
2026/08/12-17:18:28.670715 17381f000 Delete type=3 #1
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000004
MANIFEST-000007
+3 -5
View File
@@ -1,5 +1,3 @@
2026/08/12-17:01:00.590427 17430f000 Recovering log #3
2026/08/12-17:01:00.592952 17430f000 Level-0 table #5: started
2026/08/12-17:01:00.595458 17430f000 Level-0 table #5: 362253 bytes OK
2026/08/12-17:01:00.595945 17430f000 Delete type=0 #3
2026/08/12-17:01:00.596079 17430f000 Delete type=3 #2
2026/08/12-17:19:00.068863 171de3000 Recovering log #6
2026/08/12-17:19:00.069245 171de3000 Delete type=0 #6
2026/08/12-17:19:00.069278 171de3000 Delete type=3 #4
+5 -1
View File
@@ -1 +1,5 @@
2026/08/12-17:00:45.645431 173837000 Delete type=3 #1
2026/08/12-17:18:41.342413 172e97000 Recovering log #3
2026/08/12-17:18:41.345683 172e97000 Level-0 table #5: started
2026/08/12-17:18:41.349608 172e97000 Level-0 table #5: 546705 bytes OK
2026/08/12-17:18:41.349967 172e97000 Delete type=0 #3
2026/08/12-17:18:41.350026 172e97000 Delete type=3 #2
Binary file not shown.
Binary file not shown.
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.620152 174b1b000 Recovering log #3
2026/08/12-17:01:00.620322 174b1b000 Level-0 table #5: started
2026/08/12-17:01:00.620600 174b1b000 Level-0 table #5: 21613 bytes OK
2026/08/12-17:01:00.620886 174b1b000 Delete type=0 #3
2026/08/12-17:01:00.621007 174b1b000 Delete type=3 #2
2026/08/12-17:19:00.093726 172dfb000 Recovering log #3
2026/08/12-17:19:00.094281 172dfb000 Level-0 table #5: started
2026/08/12-17:19:00.094522 172dfb000 Level-0 table #5: 21613 bytes OK
2026/08/12-17:19:00.094764 172dfb000 Delete type=0 #3
2026/08/12-17:19:00.094800 172dfb000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.677562 173837000 Delete type=3 #1
2026/08/12-17:18:28.666982 172807000 Delete type=3 #1
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.630921 175327000 Recovering log #3
2026/08/12-17:01:00.631535 175327000 Level-0 table #5: started
2026/08/12-17:01:00.631994 175327000 Level-0 table #5: 43953 bytes OK
2026/08/12-17:01:00.632236 175327000 Delete type=0 #3
2026/08/12-17:01:00.632279 175327000 Delete type=3 #2
2026/08/12-17:19:00.104140 171de3000 Recovering log #3
2026/08/12-17:19:00.104725 171de3000 Level-0 table #5: started
2026/08/12-17:19:00.105236 171de3000 Level-0 table #5: 43953 bytes OK
2026/08/12-17:19:00.105498 171de3000 Delete type=0 #3
2026/08/12-17:19:00.105544 171de3000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.673366 173837000 Delete type=3 #1
2026/08/12-17:18:28.663164 17402b000 Delete type=3 #1
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.621952 173b03000 Recovering log #3
2026/08/12-17:01:00.622656 173b03000 Level-0 table #5: started
2026/08/12-17:01:00.622997 173b03000 Level-0 table #5: 33484 bytes OK
2026/08/12-17:01:00.623263 173b03000 Delete type=0 #3
2026/08/12-17:01:00.623396 173b03000 Delete type=3 #2
2026/08/12-17:19:00.095716 173607000 Recovering log #3
2026/08/12-17:19:00.096342 173607000 Level-0 table #5: started
2026/08/12-17:19:00.096667 173607000 Level-0 table #5: 33484 bytes OK
2026/08/12-17:19:00.096950 173607000 Delete type=0 #3
2026/08/12-17:19:00.096997 173607000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.684501 174043000 Delete type=3 #1
2026/08/12-17:18:28.675786 17381f000 Delete type=3 #1
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.606835 173b03000 Recovering log #3
2026/08/12-17:01:00.607010 173b03000 Level-0 table #5: started
2026/08/12-17:01:00.607348 173b03000 Level-0 table #5: 7590 bytes OK
2026/08/12-17:01:00.607685 173b03000 Delete type=0 #3
2026/08/12-17:01:00.607721 173b03000 Delete type=3 #2
2026/08/12-17:19:00.081802 173607000 Recovering log #3
2026/08/12-17:19:00.082258 173607000 Level-0 table #5: started
2026/08/12-17:19:00.082491 173607000 Level-0 table #5: 7590 bytes OK
2026/08/12-17:19:00.082869 173607000 Delete type=0 #3
2026/08/12-17:19:00.082938 173607000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.616533 173837000 Delete type=3 #1
2026/08/12-17:18:28.596786 172807000 Delete type=3 #1
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.633097 175327000 Recovering log #3
2026/08/12-17:01:00.633441 175327000 Level-0 table #5: started
2026/08/12-17:01:00.633701 175327000 Level-0 table #5: 16902 bytes OK
2026/08/12-17:01:00.633908 175327000 Delete type=0 #3
2026/08/12-17:01:00.633952 175327000 Delete type=3 #2
2026/08/12-17:19:00.106260 171de3000 Recovering log #3
2026/08/12-17:19:00.106423 171de3000 Level-0 table #5: started
2026/08/12-17:19:00.106676 171de3000 Level-0 table #5: 16902 bytes OK
2026/08/12-17:19:00.106920 171de3000 Delete type=0 #3
2026/08/12-17:19:00.106958 171de3000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.679109 174043000 Delete type=3 #1
2026/08/12-17:18:28.668882 172807000 Delete type=3 #1
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.625842 175327000 Recovering log #3
2026/08/12-17:01:00.627241 175327000 Level-0 table #5: started
2026/08/12-17:01:00.628063 175327000 Level-0 table #5: 82299 bytes OK
2026/08/12-17:01:00.628376 175327000 Delete type=0 #3
2026/08/12-17:01:00.628549 175327000 Delete type=3 #2
2026/08/12-17:19:00.099636 171de3000 Recovering log #3
2026/08/12-17:19:00.100694 171de3000 Level-0 table #5: started
2026/08/12-17:19:00.101317 171de3000 Level-0 table #5: 82299 bytes OK
2026/08/12-17:19:00.101608 171de3000 Delete type=0 #3
2026/08/12-17:19:00.101669 171de3000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.667698 17302b000 Delete type=3 #1
2026/08/12-17:18:28.656351 17381f000 Delete type=3 #1
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.635017 173b03000 Recovering log #3
2026/08/12-17:01:00.635233 173b03000 Level-0 table #5: started
2026/08/12-17:01:00.635361 173b03000 Level-0 table #5: 3739 bytes OK
2026/08/12-17:01:00.635751 173b03000 Delete type=0 #3
2026/08/12-17:01:00.635791 173b03000 Delete type=3 #2
2026/08/12-17:19:00.107991 1725ef000 Recovering log #3
2026/08/12-17:19:00.108128 1725ef000 Level-0 table #5: started
2026/08/12-17:19:00.108248 1725ef000 Level-0 table #5: 3739 bytes OK
2026/08/12-17:19:00.108494 1725ef000 Delete type=0 #3
2026/08/12-17:19:00.108528 1725ef000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.662265 173837000 Delete type=3 #1
2026/08/12-17:18:28.649334 172807000 Delete type=3 #1
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.608722 17430f000 Recovering log #3
2026/08/12-17:01:00.609392 17430f000 Level-0 table #5: started
2026/08/12-17:01:00.609562 17430f000 Level-0 table #5: 5770 bytes OK
2026/08/12-17:01:00.609848 17430f000 Delete type=0 #3
2026/08/12-17:01:00.609878 17430f000 Delete type=3 #2
2026/08/12-17:19:00.083995 172dfb000 Recovering log #3
2026/08/12-17:19:00.084129 172dfb000 Level-0 table #5: started
2026/08/12-17:19:00.084298 172dfb000 Level-0 table #5: 5770 bytes OK
2026/08/12-17:19:00.084575 172dfb000 Delete type=0 #3
2026/08/12-17:19:00.084614 172dfb000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.620363 17302b000 Delete type=3 #1
2026/08/12-17:18:28.599461 173013000 Delete type=3 #1
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.618540 175327000 Recovering log #3
2026/08/12-17:01:00.618669 175327000 Level-0 table #5: started
2026/08/12-17:01:00.618845 175327000 Level-0 table #5: 6939 bytes OK
2026/08/12-17:01:00.619127 175327000 Delete type=0 #3
2026/08/12-17:01:00.619268 175327000 Delete type=3 #2
2026/08/12-17:19:00.092147 171de3000 Recovering log #3
2026/08/12-17:19:00.092413 171de3000 Level-0 table #5: started
2026/08/12-17:19:00.092589 171de3000 Level-0 table #5: 6939 bytes OK
2026/08/12-17:19:00.092830 171de3000 Delete type=0 #3
2026/08/12-17:19:00.092877 171de3000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.631740 174043000 Delete type=3 #1
2026/08/12-17:18:28.608215 17381f000 Delete type=3 #1
+5 -5
View File
@@ -1,5 +1,5 @@
2026/08/12-17:01:00.612235 17430f000 Recovering log #3
2026/08/12-17:01:00.612500 17430f000 Level-0 table #5: started
2026/08/12-17:01:00.612788 17430f000 Level-0 table #5: 14767 bytes OK
2026/08/12-17:01:00.613095 17430f000 Delete type=0 #3
2026/08/12-17:01:00.613242 17430f000 Delete type=3 #2
2026/08/12-17:19:00.086848 172dfb000 Recovering log #3
2026/08/12-17:19:00.087140 172dfb000 Level-0 table #5: started
2026/08/12-17:19:00.087447 172dfb000 Level-0 table #5: 14767 bytes OK
2026/08/12-17:19:00.087737 172dfb000 Delete type=0 #3
2026/08/12-17:19:00.087788 172dfb000 Delete type=3 #2
+1 -1
View File
@@ -1 +1 @@
2026/08/12-17:00:45.623570 173837000 Delete type=3 #1
2026/08/12-17:18:28.601849 17381f000 Delete type=3 #1
+22 -8
View File
@@ -299,7 +299,7 @@ test("every roster agent names a real posting or trade and has a portrait on dis
const { ROSTER } = await import("./roster.mjs");
const { ROLES, TRADES } = await import("../postings.mjs");
const { existsSync } = await import("node:fs");
assert.equal(ROSTER.length, 10, "the roster is meant to be ten agents");
assert.ok(ROSTER.length >= 10, "the roster has shrunk");
for (const a of ROSTER) {
const register = a.trade ? TRADES : ROLES;
const key = a.trade ?? a.role;
@@ -307,16 +307,27 @@ test("every roster agent names a real posting or trade and has a portrait on dis
assert.ok(existsSync(new URL(`../art/portraits/${a.portrait}.webp`, import.meta.url)),
`${a.name}: no portrait at art/portraits/${a.portrait}.webp`);
}
// Five postings and five trades, so a group choosing from this sheet sees both
// halves of character creation without anyone having to explain them.
assert.equal(ROSTER.filter(a => a.trade).length, 5, "the roster should be half trades");
// Both halves of character creation must be on the sheet, and neither may dwarf the
// other, so a group choosing from it meets both without anyone having to explain them.
// Not an exact 50/50: that was an accident of the roster being exactly ten, and
// enforcing it would mean picking characters to satisfy a ratio.
const trades = ROSTER.filter(a => a.trade).length;
const postings = ROSTER.length - trades;
assert.ok(trades > 0 && postings > 0, "the roster shows only one half of character creation");
assert.ok(Math.max(trades, postings) <= Math.min(trades, postings) * 2,
`${trades} trades against ${postings} postings — one half is dwarfing the other`);
// Two agents with the same posting are two players who thought they had picked
// different characters and did not find out until the second scene.
const jobs = ROSTER.map(a => a.trade ?? a.role);
assert.equal(new Set(jobs).size, jobs.length,
`duplicate job on the roster: ${jobs.find((j, i) => jobs.indexOf(j) !== i)}`);
});
// The "before" set is only worth having if it is the SAME ten people, so it is keyed
// off the roster rather than written out again. The build proves the harder property —
// that a civilian carries nothing the department issued — because that is where the
// expanded objects exist; this proves the table they are built from.
test("every roster agent has a before-the-department entry, and the ten cover ten trades", async () => {
test("every roster agent has a before-the-department entry, and the set covers every trade", async () => {
const { ROSTER, BEFORE } = await import("./roster.mjs");
const { TRADES } = await import("../postings.mjs");
const keys = new Set(ROSTER.map(a => a.key));
@@ -328,9 +339,12 @@ test("every roster agent has a before-the-department entry, and the ten cover te
assert.ok(b.age < a.age.chronological, `${a.name} is not younger before than after`);
}
for (const k of Object.keys(BEFORE)) assert.ok(keys.has(k), `${k} is a before with nobody after it`);
const trades = Object.values(BEFORE).map(b => b.trade);
assert.equal(new Set(trades).size, Object.keys(TRADES).length,
"the ten should cover all ten trades exactly once — that is what makes the set a demonstration");
// Covering every trade is what makes this set a demonstration of the trade half of
// character creation. It was "exactly once" while the roster was exactly ten; the
// property that actually matters is that no trade is missing.
const seen = new Set(Object.values(BEFORE).map(b => b.trade));
const missing = Object.keys(TRADES).filter(t => !seen.has(t));
assert.equal(missing.length, 0, `no roster agent came out of: ${missing.join(", ")}`);
});
/* ---------------------------------------------------------------- */
+115 -4
View File
@@ -6,8 +6,9 @@
* starter scenario uses, so a roster agent cannot drift from the generator. Change
* TRADE_BANDS and every doctor on this list changes with it.
*
* Five postings and five trades on purpose. A group picking from this sheet sees both
* halves of character creation without anybody having to explain them.
* Postings and trades in equal numbers on purpose. A group picking from this sheet
* sees both halves of character creation without anybody having to explain them, and
* no two entries share a posting or a trade.
*
* Portraits are generated art, one per agent, in art/portraits.
*/
@@ -109,7 +110,76 @@ export const ROSTER = [
talents: ["debriefer", "wrong_memory", "read_room"],
bio: "<p>A chair in comparative folklore and a reading list nobody else has "
+ "finished. Was consulted once and never quite sent home.</p>"
+ "<p><em>Anchor:</em> a photograph of a lecture theatre, taken from the back.</p>" }
+ "<p><em>Anchor:</em> a photograph of a lecture theatre, taken from the back.</p>" },
/* ---------------- second intake ---------------- */
/* Six more, written for the group that actually plays. Three postings and three
trades again, and none of the six repeats a posting or a trade already on the
sheet above, so the roster covers sixteen different jobs and no two players
pick the same character by accident. */
{ key: "pc_pollard", name: "Gareth Pollard", role: "warden", rank: "Field Officer",
portrait: "pc_pollard", chosenStyle: "reflex", species: "baseline",
age: { chronological: 47, physiological: 47 },
ch: { str: 14, siz: 15, con: 16, int: 12, pow: 13, dex: 12, cha: 11, edu: 10 },
talents: ["unblinking", "first_through"],
bio: "<p>Sits with a site all night so that nobody else has to, and writes down the "
+ "times. Has never once been found asleep and never once complained about it.</p>"
+ "<p><em>Anchor:</em> a wind-up alarm clock that has not kept time since 2003.</p>" },
{ key: "pc_ashcroft", name: "Dominic Ashcroft", role: "anchor", rank: "Senior Field Officer",
portrait: "pc_ashcroft", chosenStyle: "deliberate", species: "baseline",
age: { chronological: 38, physiological: 41 },
ch: { str: 11, siz: 12, con: 13, int: 15, pow: 17, dex: 13, cha: 12, edu: 14 },
talents: ["out_of_step", "borrowed_hour", "not_quite_here"],
bio: "<p>Holds the door open while everyone else goes through it, and stays filed "
+ "correctly for as long as that takes. Three years older than his birthday says "
+ "and does not discuss the difference.</p>"
+ "<p><em>Anchor:</em> his own school tie, cut in half; the department has the "
+ "other half.</p>" },
{ key: "pc_braithwaite", name: "Neil Braithwaite", role: "pathology", rank: "Field Officer",
portrait: "pc_braithwaite", chosenStyle: "deliberate", species: "baseline",
age: { chronological: 51, physiological: 51 },
ch: { str: 11, siz: 12, con: 12, int: 17, pow: 12, dex: 13, cha: 10, edu: 17 },
talents: ["chain_custody", "unblinking", "triage"],
bio: "<p>Establishes what a thing was, which is usually the question the case turns "
+ "on. Talks to the table, not to the room, and is right often enough that "
+ "nobody minds.</p>"
+ "<p><em>Anchor:</em> a fountain pen his father used to sign death "
+ "certificates.</p>" },
{ key: "pc_renshaw", name: "Kate Renshaw", role: "interview", rank: "Senior Field Officer",
portrait: "pc_renshaw", chosenStyle: "deliberate", species: "baseline",
age: { chronological: 44, physiological: 44 },
ch: { str: 10, siz: 11, con: 12, int: 15, pow: 14, dex: 12, cha: 17, edu: 15 },
talents: ["debriefer", "read_room", "wrong_memory"],
bio: "<p>Sits with the witness afterwards, for as long as it takes, and is very hard "
+ "to lie to twice. Gets more out of an hour and a pot of tea than the rest of "
+ "the department gets out of a warrant.</p>"
+ "<p><em>Anchor:</em> a hair clip that belonged to a woman whose statement she "
+ "never finished taking.</p>" },
{ key: "pc_sharrock", name: "Danny Sharrock", trade: "builder", rank: "Probationary",
portrait: "pc_sharrock", chosenStyle: "reflex", species: "baseline",
age: { chronological: 42, physiological: 42 },
ch: { str: 16, siz: 15, con: 15, int: 12, pow: 10, dex: 14, cha: 12, edu: 9 },
talents: ["hard_landing", "first_through"],
bio: "<p>Twenty years of sites and other people's mistakes. Knows what a building is "
+ "about to do a good few seconds before it does it, and says so, loudly.</p>"
+ "<p><em>Anchor:</em> a bent nail from the first roof he ever stripped, kept in "
+ "a tobacco tin.</p>" },
{ key: "pc_ferriby", name: "Colin Ferriby", trade: "it", rank: "Probationary",
portrait: "pc_ferriby", chosenStyle: "deliberate", species: "baseline",
age: { chronological: 29, physiological: 29 },
ch: { str: 10, siz: 12, con: 11, int: 17, pow: 12, dex: 13, cha: 10, edu: 14 },
talents: ["echo_sense", "chain_custody"],
bio: "<p>Second line, then infrastructure. Has read the logs nobody else reads and "
+ "believes them over people, which is either the reason he is here or the "
+ "reason he was let go.</p>"
+ "<p><em>Anchor:</em> a dead hard drive with his own handwriting on the "
+ "label.</p>" }
];
/**
@@ -202,5 +272,46 @@ export const BEFORE = {
+ "literature.</p>"
+ "<p><em>How they found him:</em> he was consulted once, as an academic "
+ "courtesy, and gave an answer so specific that he was never quite sent "
+ "home.</p>" }
+ "home.</p>" },
pc_pollard: { trade: "police", job: "Custody Sergeant", age: 39,
bio: "<p>Nights, on the custody desk, for eleven years. Signs people in, signs them "
+ "out, and writes down the times, which is the entire job and most of the "
+ "reason it is done properly.</p>"
+ "<p><em>How they found him:</em> he logged a detainee in and out on the same "
+ "sheet, in his own hand, forty minutes apart, and there is no detainee.</p>" },
pc_ashcroft: { trade: "scientist", job: "Research Physicist", age: 31,
bio: "<p>A university group, a beamline, and six years of measuring one thing very "
+ "carefully. Comfortable with results that are correct and unwelcome.</p>"
+ "<p><em>How they found him:</em> he published a null result nobody wanted, twice, "
+ "and the second time he included the run his supervisor had asked him to "
+ "drop.</p>" },
pc_braithwaite: { trade: "doctor", job: "Consultant Histopathologist", age: 41,
bio: "<p>Twenty years of establishing what a thing was. Talks to the specimen rather "
+ "than the room, and is right often enough that nobody minds.</p>"
+ "<p><em>How they found him:</em> he reported a sample as being from a tissue "
+ "type he could not name, in writing, under his own signature, and refused to "
+ "amend it.</p>" },
pc_renshaw: { trade: "entertainer", job: "Actor", age: 37,
bio: "<p>Eleven years of rep, tour and two soaps, and a decade before that of front "
+ "of house. Learned to read a room from the wrong side of the lights and never "
+ "stopped doing it.</p>"
+ "<p><em>How they found her:</em> she took a witness statement off a stranger in "
+ "a foyer, unasked, in longhand, and it is the best one anybody took.</p>" },
pc_sharrock: { trade: "builder", job: "Site Foreman", age: 39,
bio: "<p>Twenty years of sites, scaffold and other people's mistakes, and a voice "
+ "that carries across one. Knows what a building is about to do.</p>"
+ "<p><em>How they found him:</em> he stopped a pour because a wall was in the "
+ "wrong place, and he was right, and the drawings agreed with him afterwards "
+ "and had not before.</p>" },
pc_ferriby: { trade: "it", job: "Infrastructure Engineer", age: 28,
bio: "<p>Second line, then infrastructure. Has read the logs nobody reads and "
+ "believes them over people, which has cost him two jobs.</p>"
+ "<p><em>How they found him:</em> he kept a packet capture his employer told him "
+ "twice to delete, because the timestamps in it do not run in order.</p>" }
};