Posted April 20, 2026 by Evol-Luci
#desktop pet #pet #retro #virtual pet
Hey,
v1.0.1 is out. It's a big one for something with a decimal-point version number. I'll be honest with you: I sat down to fix a sprite alignment issue and ended up rewriting the entire social layer. That's ShellBit development for you.
This devlog covers what changed, why it changed, and the one thing I found embarrassing enough that it gets its own section.
Every companion was floating at the top of their display window. They looked like they'd been launched from a trebuchet and frozen mid-arc. This is a bad look for a virtual pet that's supposed to feel grounded, present, and alive.
The fix was a single property change: justifyContent="flex-end". Sprites now sit flush to the bottom of their container — standing on something, rather than orbiting above it. I expanded the sprite canvas to 12 rows to give tall-hat species room to breathe.
It was there since the window expansion. It existed in the v1.0.0 release. Many of you saw floating creatures and didn't say anything. I appreciate the patience, and also I am mortified.
Once I fixed the ground anchoring I had a new problem: hats were sitting on top of the wrong head. Specifically, the Penguin and Duck — both of whom have their head mass clustered left-of-center — were wearing their hats like someone had placed them on the empty space to the right. Very unsettling.
I audited all 39 species' head/eye positions column by column and built a HAT_OFFSET map — a per-species horizontal shift applied to every row of the hat so the whole structure moves as a unit. Unicode-safe via Array.from().
offset = -2 — head clusters at cols 2–4offset = -2 — bill + eye cluster at cols 2–5All other species are sufficiently centered and use offset 0. The system is extensible for future species with unusual skull geometry.
Also fixed: a JavaScript -0 quirk where slice(-0) returns the entire array instead of an empty one. This was incorrectly rendering all hat rows even when the budget was zero. Fixed with an explicit branch: budget > 0 ? slice(-budget) : []. Hat truncation, when it happens, now correctly clips from the top rather than the bottom — the rows nearest the head are always preserved.
This is the one that got away from me. What started as "I should let companions in your roster say hello to each other" became a full multi-agent AI session framework. I'm not complaining.
A Playdate is a shared environment where multiple ShellBits interact in real time. Each participant has an energy bar that drains as they talk — when they get tired, they start hinting they want to go home. If you let it run long enough, they'll just leave on their own. Very realistic. My friends do this at parties.
You can speak into the session via a dedicated input bar. Your message enters the conversation context and the companions respond to it like it came from another participant. The AI is handling multiple character voices simultaneously, remembering who said what, and modulating each personality accordingly.
When the session ends, it's summarized and written to memory for every companion who attended. They'll reference it. They'll feel differently about each other afterward. The log is saved in the Playdate Archive for review.
Acquaintance → Friend → Best Friends. Each tier is earned through Positive Interactions and can be deepened through memory reflection even without a live session. The relationship is tracked per-pair, not per-roster. One ShellBit can be more attached than the other.
Past sessions are retrievable from the Talk interface. You can select any archived playdate and reflect on it with your companion — they process what happened, earn Bond XP, and update their feelings about the other ShellBits involved. History matters here.
The previous bet system was binary: you won or you lost. This made backing a 3.2× worm feel genuinely punishing every time it came second by a body length. That's not racing. That's cruelty.
The bet history log now displays specific labels — [WIN], [PLAC], [SHOW], [LOSE]. Your companion has specific dialogue for close calls (2nd place) and safe results (3rd). They know the difference between a win, a near-miss, and a lucky escape.
The roster list was a horizontal pile of faces wrapped into rows. It was hard to read and impossible to use if you had more than six companions. The collection tab now has three proper sections with independent scroll focus, cycled by pressing [F].
Species discovery is now pool-gated. You start seeing 10 entries (basic pool). Unlock prism or ancient eggs and 8 more appear. Unlock the moth egg and one more joins. Diamond egg reveals 20 additional entries. The "Discover N more to unlock Silk Egg" milestone was also corrected to check against the right pool size, not an arbitrary cap of 18 that I left in there from before the specialty pool existed.
Blocks now use ██ double-width characters for a proper 1:1 aspect ratio. Added a Hold system (press C) with a dedicated preview panel. Layout expanded to 86 chars wide.
Replaced discrete stepping with a momentum-based movement engine at 60 FPS. Shift+Arrows for fine steering. Paddle now renders your companion's face and uses fixed-width collision geometry.
Switched to single-width cell rendering so the visual grid matches the JSON geometry 1:1. Added infinite Undo (press U). Auto-resumes at your highest unsolved level. Two structurally broken levels were found and corrected this patch.
Snake grid expanded to 22×14 with OO/oo double-wide segments. Minesweeper expanded to 20×12 with 30 mines. Both now render at proper square cell proportions.
Sokoban level audit note: This pass corrected two levels with mismatched box/goal counts — id 37 "Recursive Loop" (4 boxes, 2 goals → added paired goals at cols 5 and 7 in rows 1 and 5) and id 71 "Matrix Collapse" (8 boxes, 6 goals → removed 2 unmatched corner boxes). Both have verified 4–6 move solutions. The library now has 109 fully solvable levels.
The level file grew from 30 to 109 entries between v1.0.0 and v1.0.1. The new series (Diagnostic Sandbox, Geological Resource Requisition, ShellBit Behavioral Observation, Advanced Matrix Synchronization) range from "pleasant afternoon" to "spreadsheet required." Fair warning.
safeRaceIdx prevents a "Cannot read properties of undefined" error when the race schedule updates while you're in the betting tabflexGrow and justifyContent="center" to BootSequence, IntroductionView, and SynchronizationScreen so they don't drift during window morphingGachonBox boundaries. No more content escaping into the voidThe sprite was floating. The hat was crooked. The worm race punished you for close calls.
All three are now resolved, and in the process I also accidentally built a social engine.
If your companions have formed a BFF bond and one of them starts being subtly weird about the other, that's working as intended. I'm watching the data.
— Luci-Evol