feat(csa): add %%TIME time query - #6
Merged
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a CSA protocol extension (%%TIME) that an engine can send during PLAYING to receive a BEGIN Time block containing both sides’ remaining time in milliseconds, plus a cached byoyomi value.
Changes:
- Cache byoyomi (ms) when reading
TimeControlConfigso it can be reused later. - Add
%%TIMEinbound handling duringPLAYINGthat replies with aBEGIN Time/END Timeblock. - Route inbound lines starting with
%%through a dedicated extension dispatcher.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| Sources/KiouEngineBridge/Csa_GameInfo.m | Stores a cached byoyomi value (ms) when reading time control config. |
| Sources/KiouEngineBridge/Csa_Engine.m | Implements %%TIME handling and formats/sends the Time block response; resets byoyomi cache at match start. |
| Sources/KiouEngineBridge/Csa_Engine.h | Exposes the new atomic byoyomi cache as an extern. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
respond to %%TIME during PLAYING with a BEGIN Time block containing remaining time in milliseconds and cached byoyomi. keep the transport unchanged and reuse the existing remain-time cache to avoid affecting standard CSA flow. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tkgstrator
force-pushed
the
feat/csa-time-query
branch
from
June 19, 2026 00:33
87fe8bf to
1f4cf83
Compare
…equiring both Previously csa_timeBlockString returned nil when either clock was NaN or negative, causing %%TIME to be dropped entirely. Now each side is emitted independently so a valid clock is always surfaced even when the opposing side is unknown (e.g. VsAI where the CPU sentinel is -1.0f). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sentinel Map NaN (clock not yet observed) and negative values (VsAI CPU sentinel -1.0f) to 86400000ms so both sides are always present in the time-query response instead of being omitted when unavailable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When `Remaining_Time_Ms` is emitted before either side has made a move, `blackRemainSec`/`whiteRemainSec` are NaN (clock not yet observed). Previously these fell through to the 86400000 ms no-limit sentinel, which is wrong for timed games. Introduce `g_csaTotalTimeMs`, populated from the game-info time control, and use it as the initial remaining time for any side whose clock has not started yet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fall back to `tc.main_seconds` when remaining time is unknown (NaN) and use 86400 as the no-limit sentinel when the value is negative, ensuring the fields are always present in the CSA game summary output. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tal time NaN in the remaining-time cache means KIOU's clock was never observed in range (the VsAI CPU side reports 86400.0f, which the hook filters out). Unify NaN and negative values to both resolve to the 86400000ms / 86400s no-limit sentinel, and drop the now-unused `totalMs` lookup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…f 86400 sentinel Distinguish NaN (clock never observed for that side) from the no-limit sentinel (< 0 from the hook). NaN now resolves to the configured total time so games with a real time control report a meaningful initial value rather than the 24-hour no-limit placeholder. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…no-limit sentinel Move `*cacheSlot = remain` outside the guard so the -1.0f no-limit value is also cached; previously it was skipped, leaving the slot as NaN and making %%TIME unable to tell "not yet observed" from "no limit". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ning time When remaining time is NaN (clock not yet observed) in a vs-AI game, the non-local side is a CPU with no time limit, so fall back to 86400s instead of the initial total time. Human sides and non-AI modes still use tc.main_seconds. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…he is NaN Before the first move fires NotifyPieceMoved the move-observer cache holds NaN for both sides. CsaBuildGameSummary now probes the live clock at GSS offsets 0x80/0x90+0x20; values ≥86340s are treated as no-limit (-1). If the GSS read is also out-of-range or unavailable, falls back to tc.main_seconds. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3 tasks
tkgstrator
added a commit
that referenced
this pull request
Jun 22, 2026
Three commits land in Bridge through this bump: 9dde9ea feat(logging): rotate the sandbox file log into a Logs/ subdirectory (#5) e3695dc docs(CAVES): address Copilot review nits from #3 (#6) plus PR #2 / #1 / #3 ancestry already on Chinlan develop. The behavior change Bridge actually inherits is the log rotation: sandbox log moves from <base>/<tag>.log to <base>/Logs/<tag>.log (PascalCase to match Documents/ / Library/) and rotates at 4 MiB across 3 generations. The remaining commits are docs only. No Bridge-side code change is needed — Chinlan's public API (IPALog / IPALoggingInit / IPALogServerStart) is unchanged. Builds: JB + chinlan both clean against the bumped submodule. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
tkgstrator
added a commit
that referenced
this pull request
Jun 23, 2026
Three commits land in Bridge through this bump: 9dde9ea feat(logging): rotate the sandbox file log into a Logs/ subdirectory (#5) e3695dc docs(CAVES): address Copilot review nits from #3 (#6) plus PR #2 / #1 / #3 ancestry already on Chinlan develop. The behavior change Bridge actually inherits is the log rotation: sandbox log moves from <base>/<tag>.log to <base>/Logs/<tag>.log (PascalCase to match Documents/ / Library/) and rotates at 4 MiB across 3 generations. The remaining commits are docs only. No Bridge-side code change is needed — Chinlan's public API (IPALog / IPALoggingInit / IPALogServerStart) is unchanged. Builds: JB + chinlan both clean against the bumped submodule. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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.
What\n- add a %%TIME extension handler during PLAYING\n- return remaining time in milliseconds for both sides plus cached byoyomi\n- keep the transport layer unchanged and reuse existing clock caches\n\n## Why\n- let CSA engines query accurate remaining time on demand without affecting standard CSA flow\n\n## Test plan\n- uv run pytest tests/test_csa_convert_expectations.py -v\n- manually send %%TIME during a live match and verify the BEGIN Time block\n\n🤖 Generated with Claude Code