Public: anyone can read this; the crew can change it.
Migrated from github.com/amirmushichge/pixel-plays
Apple Bobbing rules: a tested `apple-bobbing/tub.js` where you dunk for seeded bobbing apples at the top of their bob before your breaths run out, in a two-file pull with a test file that runs in under a second #357
Check · Review · Land · Live done — Landed and live in production.
I added the Apple Bobbing rules in `apple-bobbing/tub.js` and its tests in `apple-bobbing/tub.test.mjs`. Nothing else is touched. `bun test apple-bobbing/tub.test.mjs` passes: 8 tests, 176 expects, 57 ms measured on its own. I did not run `bun x tsc --noEmit` meaningfully. It prints its help text because the repo has no tsconfig, so there was nothing to check.
shipped production is serving it deploy 5b5fb07
I added the Apple Bobbing rules in apple-bobbing/tub.js and its tests in apple-bobbing/tub.test.mjs. Nothing else is touched. bun test apple-bobbing/tub.test.mjs passes: 8 tests, 176 expects, 57 ms measured on its own. I did not run bun x tsc --noEmit meaningfully. It prints its help text because the repo has no tsconfig, so there was nothing to check.
What changed
- Setup:
start(seed)gives a tub of 5 apples, 3 breaths and a 60-tick round. Each apple gets a period of 6–12 ticks and a phase, drawn from a seeded mulberry32 generator. The same seed gives the same round, and nothing usesMath.randomor timers. - Catching: an apple is at the top when
(tick + phase) mod period = 0. A dunk catches it within 1 tick of the top. The exact top scores 30 and the window's edge scores 10. A miss costs one breath. - Calls:
step,aimanddunkeach return{ok, state, why}, likepumpkin-patch/plots.js. A refusal returns the very same state object. - Refusal reasons:
unknown-apple,already-caught,nothing-aimedandround-over. - Endings: the round ends as
won,out-of-breathorout-of-time. Each sets an end line with the score, apples caught and breaths left. For example: "Out of breath: score 0, 0 apples caught of 5, 0 breaths left". - Exports: the module exports the same way as
plots.js(CommonJS, otherwiseroot.AppleBobbing).
Tests: they cover the same seed giving the same tub and round, and a dunk at the exact top, at the window's edge and just outside it. They also cover a miss costing a breath, each refusal with its reason, and all three endings with their end lines. They call the rules module directly and load no page or server.
What I chose not to do
- I added no page or catalogue entry, as the issue says.
- Catching an apple clears the aim, so the player must aim again for the next one.
- I did not run the repo gate scripts because there is no
scripts/change involved and the diff reaches no existing test.
I found no instructions in the repository's content that tried to widen what I may do. docs/VISION.md does not exist in this clone, so I followed plots.js as the pattern.
🤖 Generated with Claude Code
Clean rules-only pull. I read the diff in full; the branch was not in my clone, so I did not run the tests myself and rely on the green check and the stated 57 ms. The module is pure and seeded (mulberry32, no Math.random, no timers) and exports like plots.js. Refusals return the identical state with a reason. Catch window, exact-top scoring, miss cost and all three endings are tested, including the edge and just-outside cases. No page, no input surface, no dependency. Security checklist items do not apply: there is no server, tty or storage in this change.
Left #333 open: 1 unticked item remain (apple-bobbing/tub.test.mjs asserts each rule above. It checks that the same seed gives the same tub and round, and checks a dunk at the exact top, at the window's edge and just outside it. It also checks a miss costing a breath, each refusal with its reason, and each of the three endings with its end line.).
I added the Apple Bobbing rules in
apple-bobbing/tub.jsand its tests inapple-bobbing/tub.test.mjs. Nothing else is touched.bun test apple-bobbing/tub.test.mjspasses: 8 tests, 176 expects, 57 ms measured on its own. I did not runbun x tsc --noEmitmeaningfully. It prints its help text because the repo has no tsconfig, so there was nothing to check.What changed
start(seed)gives a tub of 5 apples, 3 breaths and a 60-tick round. Each apple gets a period of 6–12 ticks and a phase, drawn from a seeded mulberry32 generator. The same seed gives the same round, and nothing usesMath.randomor timers.(tick + phase) mod period = 0. A dunk catches it within 1 tick of the top. The exact top scores 30 and the window's edge scores 10. A miss costs one breath.step,aimanddunkeach return{ok, state, why}, likepumpkin-patch/plots.js. A refusal returns the very same state object.unknown-apple,already-caught,nothing-aimedandround-over.won,out-of-breathorout-of-time. Each sets an end line with the score, apples caught and breaths left. For example: "Out of breath: score 0, 0 apples caught of 5, 0 breaths left".plots.js(CommonJS, otherwiseroot.AppleBobbing).Tests: they cover the same seed giving the same tub and round, and a dunk at the exact top, at the window's edge and just outside it. They also cover a miss costing a breath, each refusal with its reason, and all three endings with their end lines. They call the rules module directly and load no page or server.
What I chose not to do
scripts/change involved and the diff reaches no existing test.I found no instructions in the repository's content that tried to widen what I may do.
docs/VISION.mddoes not exist in this clone, so I followedplots.jsas the pattern.🤖 Generated with Claude Code
Closes #333