Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion client/src/side/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ each prompt on the way. Before each arrow it presses E where nothing else takes
player didn't move. It takes doors and lifts from their cell, and stairs and ladders from 1.4 tiles
off their end, near the edge of the reach. Then it runs along the High Street from a press of Shift,
checking the speed and the blend, jumps the rooftops' one-, two- and three-cell gaps, the last
running, checking it lands on the far roof, walks off the clock house's roof into the lane, opens
running, checking it lands on the far roof, and the metro's jumps up to its secrets, walks off the
clock house's roof into the lane, walks down into the metro, through it into the clinic and back up
to Banyan Row, checks a run jump at the metro's high ledge falls short, opens
the news at every terminal on E, orders at the café's counter on E, and talks to Lachlan on E. It steps Playwright's clock rather than waiting, and the *Side walk*
workflow runs it on every PR.

Expand Down
5 changes: 3 additions & 2 deletions client/src/side/maps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,21 @@ import { cellOf, climbAt, groundRow, isStanding, isWalkable } from './maps';
const map = (id: string) => village.map(id)!;

describe('the side-view maps', () => {
it('reads the five streets and every floor', () => {
it('reads the five streets, the metro and every floor', () => {
expect(village.streets.map(({ id }) => id).sort()).toEqual([
'banyan_row',
'high_street',
'kapok_walk',
'lychee_lane',
'metro',
'rooftops',
]);
expect(village.floors('coffee_shop').map(({ id }) => id)).toEqual([
'coffee_shop_floor_0',
'coffee_shop_floor_1',
'coffee_shop_floor_2',
]);
expect(village.maps.size).toBe(5 + 31);
expect(village.maps.size).toBe(6 + 32);
});

it('puts each floor on its street, four rows above the one below', () => {
Expand Down
64 changes: 60 additions & 4 deletions client/src/side/walk.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,15 +223,22 @@ async function runLeg(page: Page, api: Api, index: number): Promise<void> {
}
}

/** Over a gap on the rooftops: from `from`, right until past `takeOff`, then Space, landing on row `y` past `land`. */
type Jump = { name: string; from: Place; takeOff: number; land: number; run: boolean };
/** Over a gap: from `from`, right until past `takeOff`, then Space, landing past `land` on row `onto`, or else `from`'s. */
type Jump = { name: string; from: Place; takeOff: number; land: number; run: boolean; onto?: number };

const roof = (x: number, y: number): Place => ({ map: 'rooftops', x, y });
const metro = (x: number, y: number): Place => ({ map: 'metro', x, y });
const JUMPS: Jump[] = [
{ name: 'over the one-cell gap from the bakery', from: roof(6, 12), takeOff: 9.4, land: 10.75, run: false },
{ name: 'over the two-cell gap to the tea house', from: roof(18, 8), takeOff: 21.6, land: 23.25, run: false },
{ name: 'over the three-cell gap to the laundry, running', from: roof(26, 8), takeOff: 30.3, land: 33.25, run: true },
{ name: 'from the landing onto the catwalk over the stairwell', from: metro(1, 9), takeOff: 4, land: 6.5, onto: 7, run: true },
{ name: "from the train's roof onto the catwalk in the vault", from: metro(38, 12), takeOff: 42.3, land: 44.75, onto: 10, run: true },
{ name: 'up the tunnel wall from the pipe ledge', from: metro(76, 12), takeOff: 78.3, land: 80.75, onto: 10, run: true },
{ name: 'up the tunnel wall to the alcove', from: metro(81, 10), takeOff: 82.3, land: 84.75, onto: 8, run: true },
];
/** A run jump at the metro's high ledge, a row higher than the jump, falls back to the floor. */
const SHORT: Jump = { name: 'at the high ledge, short of it', from: metro(101, 15), takeOff: 105, land: 104, onto: 15, run: true };

/** Jumps a gap on the rooftops with Space held, and lands on the far side rather than in the lane. */
async function jumpLeg(page: Page, api: Api, jump: Jump, index: number): Promise<void> {
Expand All @@ -252,11 +259,58 @@ async function jumpLeg(page: Page, api: Api, jump: Jump, index: number): Promise
if (jump.run) await page.keyboard.press('Shift');
await run(page, 100);
const landed = (await api.state())!;
if (landed.y !== jump.from.y || landed.x < jump.land) {
throw new Error(`${jump.name}: landed at ${landed.x.toFixed(2)}, ${landed.y}, not on row ${jump.from.y} past ${jump.land}`);
const row = jump.onto ?? jump.from.y;
if (landed.map !== jump.from.map || landed.y !== row || landed.x < jump.land) {
throw new Error(`${jump.name}: landed at ${landed.x.toFixed(2)}, ${landed.y}, not on row ${row} past ${jump.land}`);
}
}

/** Walks along the row, running, to within `reach` of `x`. */
async function walkTo(page: Page, api: Api, x: number, reach: number, what: string): Promise<void> {
const from = (await api.state())!.x;
if (Math.abs(from - x) <= reach) return;
const key = x > from ? 'ArrowRight' : 'ArrowLeft';
await page.keyboard.down(key);
await until(page, async () => Math.abs((await api.state())!.x - x) <= reach, 40, `${what}: walking to ${x}`, FRAME_MS);
await page.keyboard.up(key);
await run(page, 200);
}

/** Presses E, or holds up or down, until the player is at `arrive`. */
async function take(page: Page, api: Api, key: 'e' | Hold, arrive: Place, what: string): Promise<void> {
if (key === 'e') await page.keyboard.press('e');
else await page.keyboard.down(key);
await until(page, async () => near(await api.state(), arrive), SECONDS_TO_ARRIVE, `${what}: arriving at ${JSON.stringify(arrive)}`);
if (key !== 'e') await page.keyboard.up(key);
await run(page, 300);
}

/** From Banyan Row down through the metro into the clinic and back, by the keys alone. */
async function metroLeg(page: Page, walk: Api, index: number): Promise<void> {
const name = 'through the metro and back';
await teleport(page, walk, { map: 'banyan_row', x: 59, y: 18 }, name);
await run(page, 300);
await page.keyboard.press('Shift');
await walkTo(page, walk, 62, REACH.cell, name);
await take(page, walk, 'e', metro(2, 9), `${name}, down the stairway`);
await shot(page, index, 'into the metro');
await walkTo(page, walk, 4, REACH.edge, name);
await take(page, walk, 'ArrowDown', metro(7, 12), `${name}, down to the ticket hall`);
await walkTo(page, walk, 19, REACH.edge, name);
await take(page, walk, 'ArrowDown', metro(22, 15), `${name}, down to the platform`);
await walkTo(page, walk, 89, REACH.cell, name);
await shot(page, index, 'at the clinic');
await take(page, walk, 'e', { map: 'clinic_floor_0', x: 1, y: 2 }, `${name}, into the clinic`);
await take(page, walk, 'e', metro(89, 15), `${name}, out of the clinic`);
await walkTo(page, walk, 22, REACH.edge, name);
await take(page, walk, 'ArrowUp', metro(19, 12), `${name}, up to the ticket hall`);
await walkTo(page, walk, 7, REACH.edge, name);
await take(page, walk, 'ArrowUp', metro(4, 9), `${name}, up to the landing`);
await walkTo(page, walk, 2, REACH.cell, name);
await take(page, walk, 'e', { map: 'banyan_row', x: 62, y: 18 }, `${name}, up to Banyan Row`);
await page.keyboard.press('Shift');
}

/** Walks off the clock house's roof and lands in the lane, a fall of eleven rows. */
async function fallLeg(page: Page, api: Api, index: number): Promise<void> {
const name = "off the clock house's roof";
Expand Down Expand Up @@ -356,6 +410,8 @@ try {
['running with Shift', (i) => runLeg(page, api, i)],
...JUMPS.map((jump): [string, (index: number) => Promise<string | void>] => [`jumping ${jump.name}`, (i) => jumpLeg(page, api, jump, i)]),
["falling off the clock house's roof", (i) => fallLeg(page, api, i)],
['through the metro and back', (i) => metroLeg(page, api, i)],
[`jumping ${SHORT.name}`, (i) => jumpLeg(page, api, SHORT, i)],
...(await api.terminals()).map((at): [string, (index: number) => Promise<string | void>] => [
`E at the terminal on ${at.map}`,
(i) => terminalLeg(page, api, at, i),
Expand Down
17 changes: 17 additions & 0 deletions content/papercraft/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,20 @@ IS-Net's weights (`isnet-general-use.onnx`, 179 MB, rembg's release) download on

[`references/`](references/) holds the five style references from #295's study (0.75 MB): street,
house, rooftops, furniture and characters. The build reads them from here, never from `docs/`.
[`references/cartoon/`](references/cartoon/) holds #329's revised cartoon references, street and
interior (0.47 MB), for the tunnels.

## The tunnels

The metro under the village (`content/street/README.md`'s *The metro*) is painted in #329's revised
cartoon, kept a little dirty: its layers (`TUNNEL_LAYERS`), the furniture marked `cartoon`, the
clinic's front (its `Look` is `cartoon`) and its room paper (`CARTOON_PAPERS`). Their prompts end in
`painter.CARTOON` rather than the papercraft style, and they're painted from the cartoon references.
The rest of the pipeline is the same, with three additions:

- `near-metro` is a solid tiled wall 4.6 m tall, so it hides the foot of `mid-metro`, which the
client draws 2.75 m up. It's cut as a `ground` piece, keyed on its top row's colour (`cut`
`above`), since the wall fills its sides.
- The clinic's `Look` is `whole`: one painting however wide, with no seam where units would meet.
- The metro's catwalks and steps are furniture drawn over the street's own ledges and steps, which
stay papercraft.
Binary file added content/papercraft/fronts/clinic.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/bedroll.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/breaker_box.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/crates.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/dead_terminal.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/freight_lift.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/metro_bench.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/metro_entrance.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/metro_steps.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/pipes.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/rubble.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/scrap_stall.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/ticket_machine.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/train_carriage.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/tunnel_arch.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/furniture/turnstile.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/glow/clinic.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/layers/far-metro.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/layers/front-metro.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/layers/ground-metro.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/layers/metro-vault.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/layers/mid-metro.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/papercraft/layers/near-metro.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
79 changes: 79 additions & 0 deletions content/papercraft/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@
"width": 6,
"x": 4
},
"clinic": {
"door": 1,
"height": 3,
"id": "clinic",
"interior": true,
"murals": [],
"storeys": 1,
"street": "metro",
"width": 10,
"x": 88
},
"clock_house": {
"door": null,
"height": 11,
Expand Down Expand Up @@ -287,6 +298,10 @@
2,
1
],
"bedroll": [
2,
1
],
"bench": [
2,
1
Expand All @@ -303,6 +318,10 @@
1,
2
],
"breaker_box": [
1,
2
],
"bush": [
1,
1
Expand All @@ -311,10 +330,22 @@
2,
1
],
"catwalk": [
8,
2
],
"counter": [
3,
1
],
"crates": [
1,
1
],
"dead_terminal": [
1,
2
],
"espresso_machine": [
1,
1
Expand All @@ -323,6 +354,10 @@
2,
2
],
"freight_lift": [
2,
4
],
"grinder": [
1,
1
Expand Down Expand Up @@ -355,6 +390,18 @@
3,
1
],
"metro_bench": [
2,
1
],
"metro_entrance": [
1,
3
],
"metro_steps": [
4,
4
],
"news_terminal": [
1,
2
Expand All @@ -375,6 +422,10 @@
4,
1
],
"pipes": [
12,
1
],
"plant": [
1,
1
Expand All @@ -391,6 +442,14 @@
8,
1
],
"rubble": [
2,
1
],
"scrap_stall": [
3,
2
],
"sewing_machine": [
1,
2
Expand All @@ -415,10 +474,26 @@
2,
1
],
"ticket_machine": [
1,
2
],
"train_carriage": [
10,
3
],
"tree": [
2,
4
],
"tunnel_arch": [
3,
8
],
"turnstile": [
2,
1
],
"wardrobe": [
1,
2
Expand All @@ -434,6 +509,9 @@
"stairs"
],
"rooms": {
"clinic": [
"clinic"
],
"coffee_shop": [
"cafe",
"cafe_upstairs",
Expand Down Expand Up @@ -499,6 +577,7 @@
"high_street": 84,
"kapok_walk": 34,
"lychee_lane": 68,
"metro": 110,
"rooftops": 60
}
}
Loading
Loading