Create docs/ folder at repo root and move documentation files: - CONNECTION_ARCHITECTURE.md (new comprehensive connection docs) - COMMAND_PROTO_USAGE_ANALYSIS.md - DEPROTO_PLAN.md - SCALA3_MODERNIZATION.md - actions-model-usage-analysis.md - occupants-optimization-report.md - scala3-reflection-issues.md CLAUDE.md remains at root (project instructions for Claude Code). Connection architecture documentation includes: - gRPC bidirectional streaming protocol details - Client-side connection management (PersistentClientConnection) - Server-side implementation (EagleServiceImpl) - nginx proxy configuration and timeouts - Timeout settings across all layers (client, nginx, server) - Eagle ↔ Shardok communication flow Critical findings: - 🔴 SECURITY: Shardok internal interface exposed without auth in nginx config - Mystery "2-minute timeout" doesn't exist in code (all timeouts are 5-20 minutes) - No state resync mechanism after connection drops during Shardok - Inefficient dual-layer heartbeat (HTTP/2 + application level) Hypotheses for remote player connection issues: - Most likely: NAT/firewall timeout at player's router/ISP (60-120s) - HTTP/2 keepalive (45s) may not be frequent enough to keep NAT alive - Shardok's bursty traffic pattern may appear "idle" at transport layer Recommendations: 1. Fix Shardok internal interface security vulnerability 2. Add precise connection drop logging with timestamps 3. Reduce HTTP/2 keepalive from 45s to 15s 4. Get network diagnostics from affected remote player 5. Implement state resync mechanism for Shardok 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
8.2 KiB
CommandProto Usage Analysis in shardok/ai
This document analyzes all remaining usages of CommandProto (protocol buffer representation) in the AI code and identifies opportunities to eliminate proto conversion by using ShardokCommand directly.
Summary
Total CommandProto usages found: 42 locations across 9 files
Eliminated: 6 usages (14%) - ✅ Phase 1 Complete Can be eliminated: ~14 usages (33%) Must keep (for now): ~22 usages (53%)
Files with CommandProto Usage
1. AICommandFilter.cpp (6 usages) - ✅ COMPLETED (PR #4505)
Location: Lines 146, 189, 252, 356, 387, 428
Original usage:
const auto cmdProto = cmd.GetCommandProto();
if (!cmdProto.has_target()) { ... }
const auto& targetCoords = cmdProto.target();
if (!cmdProto.has_actor()) { ... }
const auto unitId = cmdProto.actor().value();
Replaced with:
const int targetRow = cmd.GetTargetRow();
const int targetCol = cmd.GetTargetColumn();
if (targetRow < 0 || targetCol < 0) {
throw ShardokInternalErrorException("Command missing required target");
}
const Coords targetCoords(targetRow, targetCol);
const int actorId = cmd.GetActorUnitId();
if (actorId < 0) {
throw ShardokInternalErrorException("Command missing required actor");
}
Status: ✅ ELIMINATED - Replaced with direct accessors + exception handling Impact: Eliminated 6 proto conversions in hot path (command filtering) Completed: Phase 1, PR #4505
2. ShardokAIClient.cpp (8 usages)
Location: Lines 83, 86, 87, 102, 105, 237, 261, 311, 356
Usage breakdown:
a) Command validation (lines 83-87)
void CheckCommand(const CommandProto &realDescriptor, const CommandProto &guessedDescriptor) {
differencer.IgnoreField(CommandProto::descriptor()->FindFieldByNumber(
CommandProto::kFollowUpCommandTypesFieldNumber));
Status: ❌ MUST KEEP - Uses protobuf reflection for comparison Reason: Comparing proto messages for correctness checking requires proto API
b) GetAvailableCommandProtos calls (lines 105, 356)
const auto guessedCommands = guessedEngine.GetAvailableCommandProtos(playerId, false);
if (const auto &availableCommands = engine.GetAvailableCommandProtos(playerId, false);
Status: ✅ CAN REPLACE - Should use GetAvailableCommandsForAIPlayer() instead
Impact: This is a major conversion point - converts entire command list to protos
Priority: HIGH (converts all commands to proto unnecessarily)
c) Strategy selector methods (lines 102, 237, 261, 311)
const vector<CommandProto> &realAvailableCommands) const -> CommandChoiceResults
Status: ✅ CAN REPLACE - Depends on fixing strategy selector signatures Priority: MEDIUM (depends on other refactors)
3. IterativeDeepeningAI.cpp/hpp (4 usages)
Location: Lines 41, 272 (cpp), 73, 96 (hpp)
Current usage:
const std::vector<CommandProto>& commands,
Status: ✅ CAN REPLACE - These methods should accept CommandListSPtr instead
Impact: Major - this is the main AI search algorithm
Priority: HIGH (core AI algorithm)
Note: IterativeDeepeningAI already receives commands as proto vectors. The conversion happens upstream at the entry point. Need to trace back to find where GetAvailableCommandProtos is called.
4. AIFleeDecisionCalculator.cpp/hpp (6 usages)
Location: Lines 17, 38, 39, 62, 63 (hpp), 18, 19, 137, 138 (cpp)
Current usage:
const vector<CommandProto>& availableCommands,
const vector<CommandProto>::const_iterator& fleeCommand,
Status: ✅ CAN REPLACE - Should use CommandListSPtr and indices instead
Impact: Flee decision logic could avoid proto conversion
Priority: MEDIUM
5. AIAttackerStrategySelector.cpp/hpp (2 usages)
Location: Line 30 in both files
Current usage:
const vector<CommandProto>& availableCommands) -> AIStrategy
Status: ⚠️ PARTIALLY REPLACEABLE - Currently doesn't use the commands parameter Current implementation:
const vector<CommandProto>& /*availableCommands*/) -> AIStrategy {
// Parameter is commented out - not used!
return AIStrategy::DEFAULT;
}
Priority: LOW (parameter unused, but signature should be consistent)
6. AICommandEvaluator.hpp (1 usage)
Location: Line 27
Current usage:
using CommandProto = net::eagle0::shardok::api::CommandDescriptor;
Status: ⚠️ CHECK USAGE - Type alias, need to check if used Priority: LOW (just a type alias)
7. AIScoreCalculator.hpp (1 usage)
Location: Line 24
Current usage:
using CommandProto = net::eagle0::shardok::api::CommandDescriptor;
Status: ⚠️ CHECK USAGE - Type alias, need to check if used Priority: LOW (just a type alias)
8. AIWaterCrossingCommandChooser.hpp (1 usage)
Location: Line 20
Current usage:
using CommandProto = net::eagle0::shardok::api::CommandDescriptor;
Status: ⚠️ CHECK USAGE - Type alias, need to check if used Priority: LOW (just a type alias)
Key Conversion Points (Entry Points)
ShardokEngine::GetAvailableCommandProtos()
This method converts the entire command list from CommandListSPtr to vector<CommandProto>.
Current flow:
ShardokEngine::GetAvailableCommandsForAIPlayer() → CommandListSPtr
↓ (conversion)
ShardokEngine::GetAvailableCommandProtos() → vector<CommandProto>
↓
AI algorithms (IterativeDeepeningAI, etc.)
Desired flow:
ShardokEngine::GetAvailableCommandsForAIPlayer() → CommandListSPtr
↓ (no conversion!)
AI algorithms use CommandSPtr directly
Recommendations by Priority
HIGH Priority (Performance-critical hot paths)
-
AICommandFilter.cpp (6 usages)
- Replace
cmd.GetCommandProto()with direct accessor methods - Use
GetActorUnitId(),GetTargetRow(),GetTargetColumn() - Impact: Eliminates 6 proto conversions per filtered command
- Replace
-
ShardokAIClient.cpp - GetAvailableCommandProtos calls
- Replace calls to
GetAvailableCommandProtos()withGetAvailableCommandsForAIPlayer() - Impact: Eliminates conversion of entire command list
- Replace calls to
-
IterativeDeepeningAI
- Change signature from
vector<CommandProto>toCommandListSPtr - Impact: Main AI search algorithm avoids proto conversion
- Change signature from
MEDIUM Priority
-
AIFleeDecisionCalculator
- Change to use
CommandListSPtrand indices - Impact: Flee decision logic avoids proto
- Change to use
-
ShardokAIClient strategy methods
- Update signatures to use
CommandListSPtr - Cascades to strategy selectors
- Update signatures to use
LOW Priority
- Type aliases
- Remove unused
using CommandProtodeclarations - Clean up imports
- Remove unused
Migration Strategy
Phase 1: Low-hanging fruit (AICommandFilter) - ✅ COMPLETED (PR #4505)
- ✅ Replaced 6 proto conversions with direct accessor calls
- ✅ Added exception handling for missing actor/target data
- ✅ No signature changes needed
- ✅ Immediate performance benefit
- PR: #4505
Phase 2: Entry point (ShardokAIClient)
- Replace
GetAvailableCommandProtos()calls withGetAvailableCommandsForAIPlayer() - Update method signatures in ShardokAIClient
Phase 3: Core AI (IterativeDeepeningAI)
- Change IterativeDeepeningAI to accept
CommandListSPtr - This is the biggest change but has highest impact
Phase 4: Supporting systems
- Update AIFleeDecisionCalculator
- Update strategy selectors
- Clean up type aliases
Phase 5: Validation code
- Keep proto-based validation as-is (uses reflection)
- Consider if validation is still needed in production
Notes
- MCTS already converted: The MCTS code path already uses
CommandListSPtrdirectly - Proto still needed: For serialization/network communication (not in AI hot path)
- Validation: Proto comparison in CheckCommand() should remain (uses proto reflection)
Estimated Impact
Proto conversions eliminated: ~20-25 per command choice Performance gain: Eliminates hundreds of allocations per AI decision Code simplification: Removes proto conversion layer from AI
Before:
Command → Proto → AI Decision
After:
Command → AI Decision (direct)