Dog self-play fetch, and the delivery loop that never ended - #22
Merged
Conversation
`npm run lint` walked `CODEPATH Proj/`s vendored python venv and the `_*.js` scratch files, reporting 1484 errors and 105 warnings that all came from code this repo does not own. Lint was effectively unusable locally. CI never caught it because it checks out a clean tree where none of those untracked paths exist, so the break only ever showed up on a real working copy. Mirror the .gitignore entries in the flat-config ignore list. Lint now exits 0 with no warnings.
pets.js already carried the comment "tray/menu wording differs per species so the app never says treat at a dog that is actually being handed a ball", but that is exactly what shipped: the dog menu read "Give a treat" with a bone while giveTreat() sent the `ball` channel. The label lived in pets.js and the channel was chosen by a separate conditional in main.js, so the two drifted. Give each species one `giveLabel` + `giveChannel` pair and read both from the same registry entry, which deletes the conditional in giveTreat(). `playLabel` was dead on arrival (defined, never referenced); it is now `playNoun` + `playToggleLabel` and actually wired, so a dog owner sees "Ball to chase" and "Work mode (stay put, no ball)" instead of two hardcoded mentions of a butterfly. Two tests lock it: every species must expose all four fields and a give channel the preload really subscribes to, and the wording must match the payload.
Delivering set the ball to 'rest' about 6px from the dog, which is well inside FETCH_GRAB (22px). On the very next frame the rest branch saw a ball within reach, picked it up, found itself already home, and "delivered" it again without moving. That loop ran at frame rate and never terminated. Driving one throw through the overlay VM for 72 simulated seconds: 511 ball phase flips, 254 heart-and-chirp bursts, and `pantUntil` pushed forward every frame so the dog panted permanently. The ball was never forgotten either, because the 45s timer restarted on each bogus delivery. Only the FIRST fetch looks correct, which is why a hand test passes and this shipped. Mark a ball the dog has carried home as delivered and leave it alone. Same throw now runs 5 phase flips, one burst, one 4.2s pant, and the ball is forgotten on schedule. tests/fetch.test.js pins the whole cycle: the fly/rest/carry sequence, exactly one delivery per throw, the pant timer going quiet, and the ball being cleaned up.
Self-play was cat-shaped: whatever species you picked, stepping away summoned a butterfly. A dog stalking a butterfly reads as a recoloured cat, and the fetch machinery to do better was already there, only ever triggered by the tray. Route self-play by species. A cat still gets its butterfly; a dog noses its own ball out, chases it down and carries it home, on the same idle gates and the same timers, so neither species feels livelier than the other. The tray toggle governs both, and work mode, reduced motion and low power suppress both. Swapping species mid-visit flies the butterfly off rather than abandoning it: it is drawn for as long as bfOn is set, so routing dogs straight to fetch would have frozen it in mid-air on screen for the rest of the session. tests/self-play.test.js covers the routing (each species gets its own companion and never the other one), the shared schedule, and every gate that turns it off.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Self-play was cat-shaped: whatever species you picked, stepping away summoned a butterfly. A dog stalking a butterfly reads as a recoloured cat, and the fetch machinery to do better was already in the renderer, only ever triggered from the tray.
Chasing that down surfaced a real bug in the dog's headline feature, so this branch fixes that first and then builds on it.
The fetch loop never terminated
Delivering set the ball to
restabout 6px from the dog, well insideFETCH_GRAB(22px). On the very next frame the rest branch saw a ball within reach, picked it up, found itself already home, and "delivered" it again without moving.Driving one throw through the overlay VM for 72 simulated seconds:
pantUntilOnly the first fetch ever looked correct, which is why a hand test passes and this shipped. A ball the dog has carried home is now marked delivered and left alone.
A dog left alone starts its own game
Self-play now routes by species. A cat still gets its butterfly; a dog noses its own ball out, chases it down and carries it home. Both run off the same idle gates and the same timers, so neither species feels livelier than the other, and the tray toggle, work mode, reduced motion and low power all suppress both.
Swapping species mid-visit flies the butterfly off rather than abandoning it. It is drawn for as long as
bfOnis set, so routing dogs straight to fetch would have frozen it in mid-air on screen for the rest of the session.Tray said "treat", app threw a ball
pets.jsalready carried the comment "tray/menu wording differs per species so the app never says treat at a dog that is actually being handed a ball" and that is exactly what shipped: the dog menu read "Give a treat 🦴" whilegiveTreat()sent theballchannel. The label lived inpets.js, the channel in a separate conditional inmain.js, so they drifted.Each species now owns one
giveLabel+giveChannelpair read from the same registry entry, which deletes the conditional.playLabelwas dead on arrival (defined, never referenced); it is nowplayNoun+playToggleLabeland actually wired, so a dog owner sees "Ball to chase" and "Work mode (stay put, no ball)" instead of two hardcoded mentions of a butterfly.npm run lintwas unusable locallyIt walked
CODEPATH Proj/'s vendored python venv and the_*.jsscratch files, reporting 1484 errors and 105 warnings from code this repo does not own. CI never caught it because it checks out a clean tree where those untracked paths do not exist. The flat-config ignore list now mirrors.gitignore.Test plan
npm test- 69 pass, up from 57 on mainnpm run lint- exits 0 with no warnings (it could not run to completion before)npm run test:boot- real Electron app launches and renderstests/fetch.test.js: the fly/rest/carry sequence, exactly one delivery per throw, the pant timer going quiet, the ball being cleaned uptests/self-play.test.js: each species gets its own companion and never the other one, the shared schedule, and every gate that turns it off