# Eagle0 AI Scoring System: Proposed Improvements

## Executive Summary

This document outlines proposed improvements to the Eagle0 AI scoring system to make it more robust and strategically intelligent. The current system makes reasonable local tactical decisions but lacks strategic depth, contextual awareness, and multi-turn planning. These improvements would transform the AI from a competent but predictable opponent into a genuinely challenging strategic adversary.

## Current System Weaknesses

### 1. Static Unit Valuation
- Fixed multipliers (1.0x infantry, 2.0x cavalry) regardless of context
- No consideration for terrain advantages or disadvantages
- Missing unit synergy and combined arms tactics
- Undervaluation of situational effectiveness

### 2. Primitive Spell Intelligence
- Hard-coded spell values that don't scale with game state
- Lightning severely undervalued (0.05 vs 38 for archery)
- Limited spell selection intelligence beyond meteor (which already has sophisticated cluster analysis)
- Poor timing for multi-turn spells like meteor preparation

### 3. Lack of Strategic Planning
- Each command evaluated independently
- No multi-turn goal coordination
- Reactive rather than proactive strategy changes
- Missing opportunity cost analysis

### 4. Limited Positional Understanding
- Simple distance-based scoring
- No chokepoint control evaluation
- Missing flanking and formation concepts
- Inadequate terrain advantage assessment

### 5. Poor Victory Condition Integration
- Static additive scoring regardless of game phase
- No dynamic priority adjustment based on time remaining
- Weak endgame transition strategies

## Proposed Improvements

### Phase 1: Immediate Impact Improvements

#### 1.1 Dynamic Unit Valuation System

**Objective**: Replace static unit multipliers with context-aware valuation

**Implementation**:
```cpp
class ContextualUnitEvaluator {
public:
    struct UnitContext {
        TerrainType terrain;
        bool inCastle;
        bool hasSupport;
        std::vector<UnitType> adjacentAllies;
        std::vector<UnitType> nearbyEnemies;
        int distanceToObjective;
    };
    
    double CalculateContextualValue(const Unit& unit, const UnitContext& context) {
        double baseValue = GetBaseUnitValue(unit);
        
        // Terrain modifiers
        baseValue *= GetTerrainModifier(unit.type, context.terrain);
        
        // Castle bonuses/penalties
        if (context.inCastle) {
            baseValue *= GetCastleModifier(unit.type);
        }
        
        // Combined arms bonuses
        baseValue *= CalculateSynergyBonus(unit.type, context.adjacentAllies);
        
        // Threat assessment
        baseValue *= AssessThreatLevel(unit, context.nearbyEnemies);
        
        return baseValue;
    }
    
private:
    double GetTerrainModifier(UnitType type, TerrainType terrain) {
        switch (type) {
            case CAVALRY:
                return (terrain == PLAINS) ? 1.4 : 
                       (terrain == FOREST) ? 0.8 : 1.0;
            case LONGBOWMEN:
                return (terrain == HILLS) ? 1.3 : 1.0;
            // ... more terrain interactions
        }
    }
    
    double GetCastleModifier(UnitType type) {
        switch (type) {
            case LONGBOWMEN: return 1.4;  // Excellent in castles
            case CAVALRY: return 0.7;     // Vulnerable in castles
            case HEAVY_INFANTRY: return 1.2; // Good defenders
            default: return 1.0;
        }
    }
};
```

**Benefits**:
- Cavalry properly devalued when attacking fortified positions
- Longbowmen bonus for castle and hill positions
- Combined arms tactics encouraged
- Situational unit effectiveness captured

#### 1.2 Intelligent Spell Scoring

**Objective**: Replace static spell constants with dynamic evaluation

**Implementation**:
```cpp
class SpellEvaluator {
public:
    double EvaluateLightning(const GameState& state, Coords target) {
        // Base damage potential
        double value = CountTargetableEnemies(state, target) * kLightningDamagePerUnit;
        
        // Bonus for hitting valuable targets
        value += EvaluateTargetValue(state, target);
        
        // Opportunity cost (could we do something better?)
        value -= CalculateOpportunityCost(state);
        
        return value;
    }
    
    double EvaluateMeteor(const GameState& state, Coords target, int turnsToLand) {
        // Predict enemy positions when meteor lands
        auto predictedPositions = PredictEnemyPositions(state, turnsToLand);
        
        // Direct damage value
        double directValue = CalculateMeteorDamage(predictedPositions, target);
        
        // Area denial value
        double denialValue = CalculateAreaDenialValue(state, target, turnsToLand);
        
        // Movement forcing value
        double forcingValue = CalculateMovementForcingValue(state, target);
        
        return directValue + denialValue + forcingValue;
    }
    
    double EvaluateAOESpell(const GameState& state, Coords center, int radius) {
        // Note: Meteor already has sophisticated cluster analysis in meteorDropRawValue()
        // This example shows how similar logic could be applied to other potential AOE spells
        auto targets = GetUnitsInRadius(state, center, radius);
        
        // Cluster bonus - more valuable against grouped enemies
        double clusterBonus = std::min(2.0, targets.size() * 0.3);
        
        double totalValue = 0;
        for (const auto& target : targets) {
            totalValue += GetUnitValue(target) * clusterBonus;
        }
        
        return totalValue;
    }
};
```

**Benefits**:
- Lightning properly valued based on target selection
- Meteor timing accounts for enemy movement patterns
- Builds on existing sophisticated meteor cluster analysis
- Area denial and positioning effects included for other spells

#### 1.3 Dynamic Victory Condition Weighting

**Objective**: Adjust priorities based on game state and time remaining

**Implementation**:
```cpp
class VictoryConditionEvaluator {
public:
    struct GamePhase {
        enum Type { OPENING, MIDGAME, ENDGAME, DESPERATE };
        Type phase;
        int roundsRemaining;
        double urgencyFactor;
    };
    
    double CalculateVictoryScore(const GameState& state, PlayerId player) {
        GamePhase phase = DetermineGamePhase(state);
        
        double castleScore = EvaluateCastleControl(state, player) * 
                           GetCastleWeight(phase);
        double unitScore = EvaluateUnitAdvantage(state, player) * 
                          GetUnitWeight(phase);
        double positionScore = EvaluatePositionalAdvantage(state, player) * 
                              GetPositionalWeight(phase);
        
        return castleScore + unitScore + positionScore;
    }
    
private:
    double GetCastleWeight(const GamePhase& phase) {
        switch (phase.phase) {
            case OPENING: return 0.3;      // Positioning important
            case MIDGAME: return 0.6;      // Balanced approach
            case ENDGAME: return 1.2;      // Castles critical
            case DESPERATE: return 2.0;    // Must secure castles
        }
    }
    
    GamePhase DetermineGamePhase(const GameState& state) {
        int roundsRemaining = GetMaxRounds() - state.current_round();
        double urgency = 1.0 - (double)roundsRemaining / GetMaxRounds();
        
        if (roundsRemaining > 20) return {GamePhase::OPENING, roundsRemaining, urgency};
        if (roundsRemaining > 10) return {GamePhase::MIDGAME, roundsRemaining, urgency};
        if (roundsRemaining > 3) return {GamePhase::ENDGAME, roundsRemaining, urgency};
        return {GamePhase::DESPERATE, roundsRemaining, urgency};
    }
};
```

**Benefits**:
- Castle control prioritized more heavily as time runs out
- Opening game focuses on positioning
- Endgame desperation properly modeled

### Phase 2: Strategic Depth Improvements

#### 2.1 Multi-Turn Strategic Planning

**Objective**: Add strategic planning layer above tactical command evaluation

**Implementation**:
```cpp
class StrategicPlanner {
public:
    enum StrategicGoal {
        SECURE_CASTLES,
        ELIMINATE_ENEMIES,
        CONTROL_CHOKEPOINTS,
        PROTECT_VIPS,
        SETUP_COMBOS
    };
    
    struct StrategicPlan {
        StrategicGoal primaryGoal;
        StrategicGoal secondaryGoal;
        std::vector<TacticalObjective> objectives;
        int turnsToExecute;
        double expectedValue;
    };
    
    StrategicPlan CreatePlan(const GameState& state, PlayerId player, int horizon) {
        auto goals = PrioritizeGoals(state, player);
        auto plan = GeneratePlan(state, goals, horizon);
        
        // Evaluate plan using lookahead
        plan.expectedValue = EvaluatePlanOutcome(state, plan);
        
        return plan;
    }
    
    void AdaptPlan(StrategicPlan& plan, const GameState& newState, 
                   const Command& opponentMove) {
        // Assess if opponent action invalidates current plan
        if (PlanStillViable(plan, newState, opponentMove)) {
            // Minor adjustments
            AdjustTactics(plan, newState);
        } else {
            // Major replanning needed
            plan = CreatePlan(newState, plan.player, plan.turnsToExecute - 1);
        }
    }
    
private:
    std::vector<StrategicGoal> PrioritizeGoals(const GameState& state, PlayerId player) {
        // Analyze current position and determine goal priorities
        auto analysis = AnalyzePosition(state, player);
        
        std::vector<StrategicGoal> goals;
        if (analysis.isWinning) {
            goals.push_back(SECURE_CASTLES);
            goals.push_back(PROTECT_VIPS);
        } else if (analysis.isLosing) {
            goals.push_back(ELIMINATE_ENEMIES);
            goals.push_back(CONTROL_CHOKEPOINTS);
        } else {
            // Balanced approach
            goals.push_back(SECURE_CASTLES);
            goals.push_back(ELIMINATE_ENEMIES);
        }
        
        return goals;
    }
};
```

**Benefits**:
- Coherent multi-turn strategies
- Adaptive planning based on opponent actions
- Goal-oriented tactical decisions

#### 2.2 Positional Intelligence System

**Objective**: Add sophisticated positional evaluation

**Implementation**:
```cpp
class PositionalEvaluator {
public:
    struct InfluenceMap {
        std::vector<std::vector<double>> controlValues;
        std::vector<std::vector<double>> threatValues;
        std::vector<std::vector<double>> mobilityValues;
    };
    
    InfluenceMap CalculateInfluenceMap(const GameState& state, PlayerId player) {
        InfluenceMap map(state.hex_map().width(), state.hex_map().height());
        
        // Calculate control influence for each unit
        for (const auto& unit : GetPlayerUnits(state, player)) {
            AddUnitInfluence(map, unit, GetUnitThreatRange(unit));
        }
        
        // Add terrain modifiers
        ApplyTerrainModifiers(map, state.hex_map());
        
        return map;
    }
    
    double EvaluatePosition(const GameState& state, PlayerId player) {
        auto influenceMap = CalculateInfluenceMap(state, player);
        
        double controlScore = EvaluateBoardControl(influenceMap);
        double chokepointScore = EvaluateChokepointControl(state, influenceMap);
        double formationScore = EvaluateFormations(state, player);
        double mobilityScore = EvaluateMobility(state, player);
        
        return controlScore + chokepointScore + formationScore + mobilityScore;
    }
    
private:
    double EvaluateChokepointControl(const GameState& state, 
                                   const InfluenceMap& influence) {
        double score = 0;
        for (const auto& chokepoint : IdentifyChokepoints(state.hex_map())) {
            if (influence.controlValues[chokepoint.x][chokepoint.y] > 0.5) {
                score += kChokepointControlValue;
            }
        }
        return score;
    }
    
    double EvaluateFormations(const GameState& state, PlayerId player) {
        double score = 0;
        auto units = GetPlayerUnits(state, player);
        
        // Look for beneficial formations
        for (size_t i = 0; i < units.size(); ++i) {
            for (size_t j = i + 1; j < units.size(); ++j) {
                score += CalculateFormationBonus(units[i], units[j]);
            }
        }
        
        return score;
    }
};
```

**Benefits**:
- Board control properly evaluated
- Chokepoint importance recognized
- Formation bonuses encouraged
- Terrain advantages captured

#### 2.3 Command Opportunity Cost Analysis

**Objective**: Evaluate what the AI gives up by choosing each command

**Implementation**:
```cpp
class OpportunityCostAnalyzer {
public:
    struct CommandOpportunity {
        Command command;
        double directValue;
        double opportunityCost;
        double netValue;
    };
    
    std::vector<CommandOpportunity> AnalyzeCommands(
        const GameState& state, 
        const std::vector<Command>& commands,
        PlayerId player) {
        
        std::vector<CommandOpportunity> opportunities;
        
        for (const auto& command : commands) {
            CommandOpportunity opp;
            opp.command = command;
            opp.directValue = EvaluateDirectValue(state, command);
            opp.opportunityCost = CalculateOpportunityCost(state, command, commands);
            opp.netValue = opp.directValue - opp.opportunityCost;
            
            opportunities.push_back(opp);
        }
        
        return opportunities;
    }
    
private:
    double CalculateOpportunityCost(const GameState& state, 
                                  const Command& chosenCommand,
                                  const std::vector<Command>& allCommands) {
        double maxAlternativeValue = 0;
        
        for (const auto& alternative : allCommands) {
            if (alternative.unit_id() == chosenCommand.unit_id() && 
                alternative != chosenCommand) {
                double altValue = EvaluateDirectValue(state, alternative);
                maxAlternativeValue = std::max(maxAlternativeValue, altValue);
            }
        }
        
        // Also consider resource opportunity costs
        double resourceCost = CalculateResourceOpportunityCost(chosenCommand);
        
        return maxAlternativeValue + resourceCost;
    }
    
    double CalculateResourceOpportunityCost(const Command& command) {
        // High-cost actions have higher opportunity cost
        switch (command.command_type()) {
            case METEOR_START: return 50;  // Locks mage for multiple turns
            case HOLY_WAVE: return 30;     // High vigor cost
            case MELEE: return 10;         // Risk of casualties
            default: return 0;
        }
    }
};
```

**Benefits**:
- Better resource management
- Reduced wasteful actions
- Improved action economy

### Phase 3: Advanced Intelligence

#### 3.1 Opponent Modeling System

**Objective**: Adapt strategy based on opponent behavior patterns

**Implementation**:
```cpp
class OpponentModel {
public:
    enum PlayStyle {
        AGGRESSIVE,
        DEFENSIVE,
        OPPORTUNISTIC,
        UNPREDICTABLE
    };
    
    struct OpponentProfile {
        PlayStyle style;
        double aggressionLevel;
        double riskTolerance;
        std::map<std::string, double> tacticFrequency;
        std::vector<Command> commonOpenings;
    };
    
    void UpdateModel(const std::vector<Command>& opponentMoves, 
                    const GameState& resultingState) {
        // Analyze opponent decision patterns
        AnalyzeAggressionLevel(opponentMoves);
        AnalyzeRiskTolerance(opponentMoves, resultingState);
        UpdateTacticFrequency(opponentMoves);
    }
    
    std::vector<Command> PredictOpponentMoves(const GameState& state) {
        auto profile = GetCurrentProfile();
        
        // Weight potential moves by opponent's historical preferences
        auto possibleMoves = GetOpponentPossibleMoves(state);
        
        std::vector<Command> predictions;
        for (const auto& move : possibleMoves) {
            double probability = CalculateMoveProbability(move, profile);
            if (probability > kPredictionThreshold) {
                predictions.push_back(move);
            }
        }
        
        return predictions;
    }
    
    void AdaptStrategy(StrategicPlan& plan, const OpponentProfile& profile) {
        switch (profile.style) {
            case AGGRESSIVE:
                // Prepare strong defenses, look for counter-attacks
                plan.primaryGoal = PROTECT_VIPS;
                plan.secondaryGoal = ELIMINATE_ENEMIES;
                break;
            case DEFENSIVE:
                // Apply pressure, force engagements
                plan.primaryGoal = CONTROL_CHOKEPOINTS;
                plan.secondaryGoal = SECURE_CASTLES;
                break;
            // ... other adaptations
        }
    }
};
```

**Benefits**:
- Adaptive strategy based on opponent type
- Prediction of opponent moves
- Counter-strategy development

#### 3.2 Machine Learning Integration Points

**Future Enhancement Areas**:

```cpp
class MLEnhancedEvaluator {
public:
    // Neural network for position evaluation
    double EvaluatePositionML(const GameState& state, PlayerId player) {
        auto features = ExtractFeatures(state, player);
        return neuralNetwork.Evaluate(features);
    }
    
    // Reinforcement learning for strategy selection
    StrategicGoal SelectStrategyRL(const GameState& state, 
                                  const OpponentProfile& opponent) {
        auto stateVector = EncodeGameState(state, opponent);
        return strategyNetwork.SelectAction(stateVector);
    }
    
    // Opening book learned from successful games
    Command GetOpeningMove(const GameState& state) {
        auto position = HashPosition(state);
        if (openingBook.contains(position)) {
            return openingBook[position].bestMove;
        }
        return Command{}; // Fall back to regular evaluation
    }
};
```

## Implementation Roadmap

### Phase 1 (3-4 weeks): Foundation
1. Implement ContextualUnitEvaluator
2. Create SpellEvaluator system
3. Add VictoryConditionEvaluator with game phase detection
4. Integrate into existing AIScoreCalculator

### Phase 2 (6-8 weeks): Strategic Layer
1. Build StrategicPlanner framework
2. Implement PositionalEvaluator with influence maps
3. Add OpportunityCostAnalyzer
4. Create goal-oriented command selection

### Phase 3 (8-12 weeks): Advanced Features
1. Develop OpponentModel system
2. Add prediction and adaptation mechanisms
3. Create ML integration points
4. Implement learning systems

## Expected Impact

### Immediate (Phase 1):
- **25-40% improvement** in tactical decision quality
- Better spell usage and timing
- More appropriate unit deployment
- Adaptive endgame strategy

### Medium-term (Phase 2):
- **50-75% improvement** in strategic coherence
- Multi-turn planning execution
- Superior positional play
- Efficient resource management

### Long-term (Phase 3):
- **AI competitive with strong human players**
- Adaptive learning from experience
- Opponent-specific strategies
- Novel tactical discoveries

## Testing and Validation

### Automated Testing:
- Unit tests for each evaluator component
- Integration tests with existing AI pipeline
- Performance regression testing
- Strategic scenario validation

### Human Testing:
- A/B testing against current AI
- Human expert evaluation sessions
- Tournament play against various skill levels
- Long-term learning validation

This comprehensive improvement plan would transform the Eagle0 AI from a competent but predictable opponent into a genuinely challenging strategic adversary that could provide engaging gameplay for both casual and expert players.