Regalia v1.0.9 #27
YDW99
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
What's Changed
Full Changelog: v1.0.8...v1.0.9
Regalia v1.0.9
📦 Release Artifacts
Regalia-v1.0.9-release.apkRegalia-v1.0.9-manual-en.htmlRegalia-v1.0.9-manual-zh.html🎯 At a Glance
1.0.9(versionCode = 109)arm64-v8a-dotprod(ARMv8.6-A DOTPROD instructions for NN inference acceleration)arm64-v8aonly (modern 64-bit devices)🔥 Headline Changes
This release concentrates on four root-cause fixes and one visual-design unification. No new features — every change is about making what already exists behave correctly.
🐛 Two CRITICAL Bug Fixes
1. PGN single-line import silently failed — 0 moves parsed, no error
Symptom
A PGN file where all headers and the movetext sit on one line (no
\nbetween[Event "..."]and1. e4) would import as zero moves. No toast, no warning — just an empty move list. The repro filePGN 2Kbug.pgn(71 half-moves, 11 variations, single line) triggered this 100% of the time.Root cause
The tag-stripping regex used the multiline
^anchor:With the
mflag,^matches at the start of each line. But in a single-line PGN, the entire string is one line — so^matches only once (at the very start). Only the first tag ([Event "Regalia"]) was stripped; the remaining tags ([Site "?"],[Date "..."], …) leaked into the movetext as invalid SAN tokens. The tokenizer skipped them all, hit the 5-consecutive-skip safety limit, and aborted.Fix
Replace the line-anchored pattern with a tag-format-specific pattern that matches
[TagName value]whereTagNamestarts with a letter:This is not anchored to line start, so it strips every tag regardless of PGN layout. It also cannot strip
[%csl ...]/[%cal ...]/[%eval ...]inside brace comments — because%is not in[A-Za-z].Companion fix — brace-comment stripping
The same single-line PGN exposed a second latent bug. The brace-comment stripper replaced
{...}with empty string:In
1. e4{[%emt 6:25:53]}e5, there's no space between}ande5. Stripping to empty producede4e5— a single invalid token that failed SAN parsing and triggered the same cascade-failure path.Verified:
PGN 2Kbug.pgnnow imports all 71 half-moves with all 11 variations intact.2. Review & stats board showed "extra kings" — phantom pieces appearing during PGN replay
Symptom
After importing a PGN and entering review mode (or opening the stats page), the board would sometimes display more kings than legally exist — a white king on g1 and a white king on e1, for example. The corruption worsened as you stepped through the moves.
Root cause — two independent defects
Defect A —
_castleSideread the wrong board (game-logic.js)The castling-detection fallback (used when the explicit
mv.castleflag is absent — the common case for moves reconstructed frommoveRecordsduring review replay) checked the globalgameState.boardandgameState.castlingRights:During PGN replay, the local state
sbeing moved differs fromgameState(which is the final state after all moves). Consider: if the white king ended the game on g1, thengameState.board[7][6]is non-empty (the king is there). When the replay reaches an earlierO-Omove (king → g1), the_destEmptycheck readsgameState(which has the king on g1) → returnsfalse→ castling detection is suppressed → only the king moves, the rook stays on h1.Every subsequent move involving that misplaced rook then fails to replay, the board state diverges, and the user sees ghost pieces.
Defect B —
stats.htmlexecuteMovefalse-positive castling (stats.html)The stats page's independent move executor used an overly broad castling detector:
This caught normal king moves (Kf1-g1, Kg7-g6) and king captures (Kxg1). A king capture to col 6/2 would: (1) treat the captured piece as the "castling rook" and reposition it (silently losing the capture); (2) illegally displace the actual rook on h1/a1; (3) corrupt the board state — manifesting as extra pieces / extra kings.
Verified: No extra kings appear at any review step for
PGN 2Kbug.pgn(which contains 4 castling moves and many king moves to col 6/2).🐛 Two HIGH-Severity Visual-Annotation Fixes
3. Variation comments contaminated main-line annotations
Symptom
After a variation containing
[%csl]/[%cal]/[%eval]tags, the next main-line move would display the variation's squares/arrows/eval — as if those annotations described the main-line position. The review board was lying about the actual position state.Root cause
The comment-extraction loop in
_parsePGNread position-specific tags from{...}blocks but never checked the parenthesis depth_depth:The variation's tags accumulated into the pending per-move payload. When the next main-line move (
e5) was seen, the payload was flushed and attached toe5— corruptinge5's annotations with variation-internal data.Fix
Gate extraction of position-specific tags on
_depth === 0:Why free-text is allowed at all depths: Free-text comments are display-only (they appear in the move-list comment popup). They don't claim to describe a position's tactical state. Position-specific tags (
[%eval]/[%csl]/[%cal]) are different — they are assertions about a specific board state, and attaching them to the wrong position is a correctness bug.4. Imported PGN moves lacked
isCheck/isCastlingSymptom
For PGN files loaded via Import PGN, the red check-path arrows and green king-escape arrows never appeared — even for moves with
+or#in the notation. Live-played games showed them correctly.Root cause
The
importPGNloop builtmoveRecordswith{notation, from, to, piece, captured, promotion, time, variations}— but omittedisCheckandisCastling. The annotation generator (_computeAndCacheVisualAnnotations) checksmoveRecords[moveIdx].isCheckto decide whether to draw red/green arrows. For imported moves, this wasundefined→ falsy → no arrows.Fix
importPGNnow computes both fields from the replayed state, mirroring the live-playexecuteMovelogic:Result: Imported games now receive the same visual-annotation treatment as live-played games. Red check arrows and green escape arrows appear correctly for every check/checkmate in the PGN.
🛡️ Robustness Hardening
5.
stats.htmlexecuteMovenow clears castling rightsPreviously,
stats.html'sexecuteMoveupdatednewState.wk/bkbut never clearednewState.castlingRightswhen the king or a rook moved, or when a rook was captured. This meant downstreambuildSAN/ state serialization could emit staleKQkqmarkers for a state where castling was no longer legal.The fix mirrors the main app's
game-logic.js makeMv/makeMvInPlacebehavior:This is a latent correctness issue (the stats page is display-only, so stale rights wouldn't corrupt gameplay), but it ensures the stats page's FEN/SAN output is always spec-compliant.
🎨 Eval-Chart Palette Unified to Blue-vs-Red (both dark & light modes)
6. One consistent color language, tuned per theme
Before
--chart-line(positive eval)--chart-fill(negative eval)#E8E8F0(near-white)#5dade2(light blue)#4a4a52(dark gray)#2c2c34(very dark gray)After — unified blue-vs-red convention
--chart-line(White advantage)--chart-fill(Black advantage)--chart-critical(current marker)#5dade2(sky blue, brighter)#e74c3c(warm red, brighter)#ffd700(gold)#2c5f8d(steel blue, deeper)#c0392b(deep red, deeper)#d4a017(gold)Plus
--chart-gridand--chart-axisretuned to warm-brown shades (#4a3020,#8a6a3a) in dark mode for palette harmony.Design rationale
#1a0a0a; light mode uses deeper, muted shades for contrast on#f0f0f3.Companion fix — data-point outlines
The data-point outline was hardcoded to two
rgbavalues that washed out in light mode:📊 Impact Summary
Files changed
🧪 Verification
All fixes were validated with purpose-built Node.js test harnesses (kept under
scripts/in the source tree):test-pgn-parse.jsPGN 2Kbug.pgn(single-line, 71 half-moves, 11 variations) imports all 71 movestest-review-kings.jsimportPGN+ review-replay flow produces no extra kings at any steptest-variation-annotations.js[%csl]/[%cal]/[%eval]leaked to main linetest-ischeck-iscastling.jsisCheck(forBxf7+) andisCastling(forO-O)Bxf7+→isCheck=true; bothO-O→isCastling=trueManual verification checklist
PGN 2Kbug.pgnimports all 71 half-moves with 11 variations📥 Installation
Option A — Direct APK install
Regalia-v1.0.9-release.apk.Option B — Build from source
See
BUILDING.mdin the source tarball for full details, including the zip-timestamp-normalization workaround for CMake/ninja.🔒 Privacy & Permissions
Regalia is a fully offline chess app. No account, no network, no tracking.
VIBRATEFOREGROUND_SERVICEPOST_NOTIFICATIONS(API 33+)READ_EXTERNAL_STORAGE/ SAFNetwork: The only network access is an optional Lichess Syzygy tablebase query (endgame lookup), which can be disabled in Settings. No telemetry, no analytics, no crash reporting to third parties.
See
PRIVACY.mdin the source tree for the full policy.📜 License & Attribution
Regalia is a combined work under dual licensing:
Per GPL v3 Section 13, these licenses are compatible for combination. Each component retains its original license. Since AGPL v3 imposes stricter requirements (including network-interaction provisions under Section 13), its obligations effectively extend to the entire combined work.
See
LICENSE-AGPL v3,LICENSE-GPL v3,LICENSE-Apache v2.0,NOTICE,NOTICE-DroidFish, andAUTHORS-stockfishin the source tree for full texts.🗺️ Roadmap
v1.0.9 closes the known correctness issues reported against v1.0.8. The next release (v1.0.10+) will focus on:
Have a bug to report or a feature to request? Open an issue on the GitHub issue tracker. Pull requests welcome — please read
BUILDING.mdfirst.📋 Changelog Archive
v1.0.8 (Phase 22–51, 2026.6.30 – 2026.7.2) — Personified animation & sound + light mode + 30-phase stability saga
Complete redesign of the move animation and sound effect system per the "Personified Chess Move Animation" and "Personified Chess Sound Effects" reference documents. Each piece has a unique personified motion characteristic and matching timbre. Light mode support added following Android Dark/Light Theme Design Principles.
Phase 51 — PGN round-trip castling fix (
_castleSidechecksmv.to.castle), move-classification label change ("Book" → "Mediocre"), eval-chart dark-mode line visibility fix.Phase 50 — Button-width TRUE root-cause fix:
.btn-rowopts out of portrait grid transform.Phase 49 — Comprehensive first-principles re-review: 6 bugs + 12 robustness issues + compliance reconciliation.
Phase 38–48 — PGN cache UI layout, castle-rights-loss root-cause fixes, button-width root-cause fix (
.btn-compactCSS class).Phase 29 — Setup-mode ⚡ button normalization, castling sound/haptic redesign, light-mode contrast fixes, WebView robustness.
Phase 22–28 — Full move-animation & sound redesign, Stockfish 18 dotprod engine integration, Web Worker multithreading, six-piece haptic personality design, comprehensive first-principles code review.
v1.0.7 (2026.6.28) — Code-quality & stability maintenance
Fixed several latent bugs uncovered by three independent code reviews (critical-move cache not invalidated on undo, lightweight board update path missing the castling-rook marker, engine-notification throttle cache staleness, stats-page PGN comment XSS risk, cross-game eval-cache pollution, CSP potentially blocking Blob Workers). Added clickable GitHub repository links for DroidFish and Stockfish in the About dialog. Refined portrait full-screen layout and Android back-button handling. Merged duplicated HTML-escape functions.
Phase 2 — Main-screen "Quick Toolbar" (Undo/Redo/Flip/AI Hint/Control Range below the board), setup-mode 🔁 manual castle-rights marker + ⚡ manual en-passant marker.
Phase 17 — Chess960 castling "king self-capture" critical bug fix.
Phase 18 —
_reviewEvalCacheLRU eviction + review move-list virtual list.Phase 19 — Comprehensive 7-subagent 28k-line code review + 20+ critical fixes.
v1.0.6 (2026.6.27) — Chess960 ECO + PGN FEN round-trip
Chess960-mode ECO opening recognition suppression, PGN with FEN header round-trip preservation, per-move selection on the stats page, unified gray-out styling, portrait New Game dialog optimization, scroll-position preservation, engine-eval FEN sanitization, king-then-rook castling gesture (essential for Chess960), Chess960 castling detection overhaul, explicit SL skill-level display.
v1.0.5 (2026.6.27) — Anti-shake + screen adaptation
Sensor-fusion board anti-shake (OIS principle), high aspect-ratio screen adaptation, notch/cutout/R-corner adaptation, phase analysis precision (opening/middlegame/endgame multi-criteria detection), review arrow shrink optimization.
v1.0.4 (2026.6.26) — Chess960 + Time Control + standardized PGN
Fischer Random Chess (Chess960) mode, Time Control, standardized PGN import/export (compliant with the 1994 PGN specification), heatmap-control-based statistics, Seldepth (selective depth) display, visual annotations (NAG &
[%csl]/[%cal]), Web Worker parallel computation, PGN cache manager, player renaming, bilingual Chinese/English UI, resign (🏳️ Resign).💎 Acknowledgments
arm64-v8a-dotprodbuild).[%csl]/[%cal]/[%eval]PGN annotation conventions.PGN 2Kbug.pgnsingle-line parse failure and the "extra kings" review-board corruption — your detailed repro files made the root-cause analysis tractable.Regalia v1.0.9 — Play offline. Analyze deeply. No account, no network, no tracking.
Built with Stockfish 18 · AGPL v3 · Compatible with Android 5.0–15 & Xiaomi HyperOS 3
AI-GEN
This discussion was created from the release Regalia v1.0.9.
All reactions