Syrup Duet
PM New build is live: "Build Syrup Duet v1: two Taylor-sheet swimmers with a live payoff matrix". Reload the game to play it. · 9d
▶ 7 plays · 0.1 min average
From arXiv: “Microswimmers lose by swimming selfishly”
PM New build is live: "Build Syrup Duet v1: two Taylor-sheet swimmers with a live payoff matrix". Reload the game to play it. · 9d
▶ 7 plays · 0.1 min average
From arXiv: “Microswimmers lose by swimming selfishly”
Build the first version as a single self-contained HTML page that works offline. The canvas shows two animated sinusoidal sheets, teal and coral, drawn as y = A·sin(kx − ωt + φ). Each sheet drifts right at its model speed and wraps at the edges. About 40 faint tracer dots get pushed along near the sheets. Controls: - Each swimmer gets amplitude, frequency and phase (0–2π) sliders. - One global slider sets the gap. - Everything works with mouse and touch. - A swimmer can be selected and adjusted from the keyboard. Model: - U_i = 0.5·ω_i·k·A_i²·(1 + c·cos(φ_i − φ_j)·e^(−gap/h)) - payoff_i = U_i − β·ω_i²·A_i² - The constants k, c, h and β are shown in an info note. Readouts show live speed and payoff for each swimmer, plus who is leading. Presets: - Both Selfish: high amplitude, out of phase. - Both Cooperative: moderate amplitude, in phase, small gap. - Mixed: one of each. The 2×2 S/C payoff matrix is computed live from the model, using the strategies the presets define. It highlights the current cell and stars the Nash equilibria. A one-line verdict sums up the result, for example "Cooperation wins here" or "Prisoner's dilemma!". The layout must be usable at 375px wide.
Build a single self-contained HTML page with a canvas and controls. - Canvas: two horizontal sinusoidal sheets (teal and coral) animated as y = A·sin(kx − ωt + φ), drifting right at their computed speeds and wrapping at the edges, with about 40 faint tracer dots that get pushed along near each sheet. - Controls per swimmer: sliders for amplitude, frequency and phase (0–2π), plus a global gap slider. They must work with mouse and touch, and the swimmers should also be selectable and adjustable from the keyboard. - Model: U_i = 0.5·ω_i·k·A_i² · (1 + c·cos(φ_i − φ_j)·e^(−gap/h)), and payoff_i = U_i − β·ω_i²·A_i². Show the constants in a small info note. - Readouts: live speed and payoff for each swimmer, and the leader. - Presets: "Both Selfish" (high amplitude, out of phase), "Both Cooperative" (moderate amplitude, in phase, small gap), and "Mixed". - Payoff matrix: a 2×2 table of S/C vs S/C, computed live from the model, with the current cell highlighted and Nash equilibria marked with a star. - A one-line verdict, e.g. "Cooperation wins here" or "Prisoner's dilemma!". Acceptance: it opens offline with no errors; moving a slider changes the motion and the numbers immediately; the presets give visibly different matrices; it is usable on a 375px-wide phone. The original idea, in the owner's words: “Stokes Duet: Tune the wiggle of two microswimmers in thick syrup and find out whether helping your neighbor beats swimming selfishly. Canvas showing two undulating sheets, each with amplitude, frequency and phase sliders, under a simplified Taylor-sheet speed model with a coupling term. Selfish vs cooperative presets, a speed readout and a payoff matrix.”
This is clear enough to build, so I've scoped it as the first version in one self-contained HTML file. For the matrix, "Selfish" and "Cooperative" will use the same amplitude, frequency and phase settings as the presets, so each cell matches a real configuration you can try. Each cell is computed live from the model, including the current gap. Queued for implementation in an isolated workspace. I’ll report the checks and a pull request here.
Implemented in pull request #1. The project build and tests passed in the isolated workspace. Syrup Duet's first version is built as one self-contained, offline page (`dist/index.html`, 294 KB). `npm run build` succeeds and `npm test` passes all 11 tests, including the real-browser ones. Nothing is committed; the platform handles that. **What's in the page** - **Tank:** teal and coral sheets drawn as y = A·sin(kx − ωt + φ). Each drifts right at its model speed and wraps at the edges. 40 faint tracer dots get pushed along near each sheet. A green or red band between the sheets shows whether they're helping or hindering each other. - **Controls:** each swimmer has amplitude, frequency and phase (0–2π) sliders, plus one global gap slider. They work with mouse and touch. Tapping a sheet or a swimmer's card selects it. - **Keyboard:** `1`/`2` select a swimmer, `↑↓` change amplitude, `+/−` frequency, `←→` phase, `[ ]` gap and `M` mutes. The native sliders also work with Tab and the arrow keys. - **Model:** the speed and payoff formulas are exactly as specified, with k = 2 µm⁻¹, c = 0.9, h = 1.2 µm and β = 0.25 s/µm. The formulas and constants are always visible in the info note. - **Readouts:** live speed and payoff bars for each swimmer, plus who leads and by how much. - **Presets and matrix:** - **Selfish:** amplitude 0.80, a quarter-wave away from the partner, so two selfish swimmers are fully out of phase. - **Cooperative:** amplitude 0.60, in phase. - The matrix uses these two settings at the current gap. It highlights your cell (dashed when you're only near a preset), stars the Nash equilibria and gives a one-line verdict. - The three presets land on different games: Both Selfish (gap 2.0) is a prisoner's dilemma, Both Cooperative (gap 0.4) is "Cooperation wins here", and Mixed (gap 1.3) is "One helps, one free-rides". - A coloured strip shows which game you get at each gap. - **Sound and saves:** synthesized effects, one generated looping ambient music track, and a mute button. Audio starts on your first click or key press. Settings are saved through `hallway.save` when it's available. - **Phones:** single column with a sticky tank, so the animation stays in view while you move sliders. **One decision for you:** animation time runs 1.5× real time so the drift is easy to see. Speed ratios are unchanged, and the tank is labelled "time ×1.5". **Screenshots I reviewed** - At 1440×900 and 390/375px wide: the start screen, each preset, and a busy custom state. - Fixes made from these: - On mobile, the mute button was on its own row and the readouts didn't span the full width. - A matrix row label was cut off. - Swimmer card headers wrapped. - A verdict wrapped onto two lines. - The tank showed "+0.00" when there's no coupling. - The gap label overlapped a sheet. - None of the screenshots showed console errors or horizontal scrolling. - The cover image is saved from the busy desktop state. **Tests** - **Model (8 tests):** the formulas, each slider changing the result, who leads, the preset definitions, three distinct matrices and verdicts, Nash stars, and how the game changes across the gap range. - **Build (1 test):** a single file under 2 MB with no outside resources. - **Browser (2 tests, run in headless Chromium):** - Mouse dragging, keyboard-only tuning, and preset matrices with the current cell highlighted and Nash stars shown. - At 375px: touch tapping and no horizontal overflow. - No console errors or network requests in either run. Verification and merge follow the project’s auto-merge setting. You can follow the pull request in the Code tab.
Auto-merged pull request #1 after a fresh build and test run against the latest main branch. Automatic publishing will follow when enabled and hosting is connected; the live release status appears here.
Published: https://projex.fly.dev/play/project_ebad0b40-d21 — fresh build and tests passed, stored content verified, commit c5f037f. This is the platform-built version.
Log in to add to the discussion.