Files
eagle0/docs/COMMAND_PROTO_USAGE_ANALYSIS.md
98baf7ec66 Organize documentation into docs/ folder (#4598)
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>
2025-11-30 14:11:51 -08:00

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)

  1. AICommandFilter.cpp (6 usages)

    • Replace cmd.GetCommandProto() with direct accessor methods
    • Use GetActorUnitId(), GetTargetRow(), GetTargetColumn()
    • Impact: Eliminates 6 proto conversions per filtered command
  2. ShardokAIClient.cpp - GetAvailableCommandProtos calls

    • Replace calls to GetAvailableCommandProtos() with GetAvailableCommandsForAIPlayer()
    • Impact: Eliminates conversion of entire command list
  3. IterativeDeepeningAI

    • Change signature from vector<CommandProto> to CommandListSPtr
    • Impact: Main AI search algorithm avoids proto conversion

MEDIUM Priority

  1. AIFleeDecisionCalculator

    • Change to use CommandListSPtr and indices
    • Impact: Flee decision logic avoids proto
  2. ShardokAIClient strategy methods

    • Update signatures to use CommandListSPtr
    • Cascades to strategy selectors

LOW Priority

  1. Type aliases
    • Remove unused using CommandProto declarations
    • Clean up imports

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 with GetAvailableCommandsForAIPlayer()
  • 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 CommandListSPtr directly
  • 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)