# 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:**
```cpp
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:**
```cpp
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)
```cpp
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)
```cpp
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)
```cpp
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:**
```cpp
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:**
```cpp
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:**
```cpp
const vector<CommandProto>& availableCommands) -> AIStrategy
```

**Status:** ⚠️ **PARTIALLY REPLACEABLE** - Currently doesn't use the commands parameter
**Current implementation:**
```cpp
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:**
```cpp
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:**
```cpp
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:**
```cpp
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

4. **AIFleeDecisionCalculator**
   - Change to use `CommandListSPtr` and indices
   - Impact: Flee decision logic avoids proto

5. **ShardokAIClient strategy methods**
   - Update signatures to use `CommandListSPtr`
   - Cascades to strategy selectors

### LOW Priority

6. **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)
```
