Skip to content

feat(csa): add %%TIME time query - #6

Merged
tkgstrator merged 10 commits into
developfrom
feat/csa-time-query
Jun 19, 2026
Merged

feat(csa): add %%TIME time query#6
tkgstrator merged 10 commits into
developfrom
feat/csa-time-query

Conversation

@tkgstrator

Copy link
Copy Markdown
Contributor

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

Copilot AI review requested due to automatic review settings June 19, 2026 00:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 TimeControlConfig so it can be reused later.
  • Add %%TIME inbound handling during PLAYING that replies with a BEGIN Time / END Time block.
  • 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.

Comment thread Sources/KiouEngineBridge/Csa_GameInfo.m
Comment thread Sources/KiouEngineBridge/Csa_Engine.m Outdated
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
tkgstrator force-pushed the feat/csa-time-query branch from 87fe8bf to 1f4cf83 Compare June 19, 2026 00:33
tkgstrator and others added 9 commits June 19, 2026 04:52
…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>
@tkgstrator
tkgstrator merged commit a30d88c into develop Jun 19, 2026
4 checks passed
@tkgstrator
tkgstrator deleted the feat/csa-time-query branch June 19, 2026 07:10
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants