using OECS; namespace OECS.PlayTest; /// /// Abstract agent that picks the action with the highest score. /// When returns 0 for all actions (the default), /// the agent behaves as a uniform random agent over legal actions. /// Ties are broken randomly. /// public abstract class GreedyAgent : IAgent { private static readonly Random _rng = new(); /// /// Returns the list of currently legal actions. /// protected abstract List GetLegalActions(World world); /// /// Scores an action. Defaults to 0 (uniform random). /// protected virtual float ScoreAction(World world, TDecision action) => 0f; public TDecision Decide(World world) { var actions = GetLegalActions(world); if (actions.Count == 0) throw new InvalidOperationException( $"{GetType().Name}: no legal actions available"); if (actions.Count == 1) return actions[0]; float bestScore = float.MinValue; var bestActions = new List(); foreach (var action in actions) { float score = ScoreAction(world, action); if (score > bestScore) { bestScore = score; bestActions.Clear(); bestActions.Add(action); } else if (score == bestScore) { bestActions.Add(action); } } return bestActions[_rng.Next(bestActions.Count)]; } }