private static double GetAdjacencyBonus(Field field, Unit unit, ExecutionOptions options) { double downBonus = options.AdjacencyDownRatio; double sideBonus = options.AdjacencySideRatio; double result = 0; foreach (var m in unit.Members) { if (m.Y < field.Height - 1) { if (field[m.Translate(MoveDirection.SouthEast)]) { result += downBonus; } else { result -= downBonus; } if (field[m.Translate(MoveDirection.SouthWest)]) { result += downBonus; } else { result -= downBonus; } } if (m.X < field.Width - 1 && field[m.Translate(MoveDirection.East)]) result += sideBonus; if (m.X > 0 && field[m.Translate(MoveDirection.West)]) result += sideBonus; } return result; }
private static IEnumerable<ExecutionResult> Calculate( Snapshot baseSnapshot, MoveDirection? move, ExecutionOptions options, int depth, double minEstimate) { var snapshot = move.HasValue ? Game.MakeMove(baseSnapshot, move.Value) : baseSnapshot; if (snapshot == null) // illegal move yield break; var estimate = SnapshotEvaluate(snapshot, options); bool nextUnit = snapshot.UnitIndex > baseSnapshot.UnitIndex; // stop recursion if (snapshot.Finished || depth <= 0 || estimate < minEstimate || nextUnit) // TODO: some diff { yield return new ExecutionResult { Commands = new [] { move.Value }, Estimate = estimate, Snapshot = snapshot }; yield break; } var candidateMoves = (MoveDirection[])Enum.GetValues(typeof (MoveDirection)); var childResults = candidateMoves .SelectMany(m => Calculate(snapshot, m, options, depth - 1, estimate)) .OrderByDescending(r => r.Estimate) .Take((int)Math.Ceiling(options.MaxWidth)); foreach (var result in childResults) { var commands = move.HasValue ? result.Commands.Prepend(move.Value).ToArray() : result.Commands; yield return new ExecutionResult { Commands = commands, Estimate = result.Estimate + CommandEncoding.GetWordsPower(commands) * options.PowerWordsBonus, Snapshot = result.Snapshot }; } }
private static void Mutate(ExecutionOptions options, double percent) { var propsDict = typeof(ExecutionOptions).GetProperties().ToDictionary(p => p.Name); foreach (var variable in Variables) { var property = propsDict[variable.Key]; double oldValue = (double)property.GetValue(options); double newValue = variable.Value.Mutate(oldValue, percent); property.SetValue(options, newValue); } }
private static ExecutionOptions Generate() { var result = new ExecutionOptions { MinEstimation = Double.MinValue }; var props = typeof(ExecutionOptions) .GetProperties() .ToDictionary(p => p.Name); foreach (var variable in Variables) { var property = props[variable.Key]; double value = variable.Value.GetRandomValue(); property.SetValue(result, value); } return result; }
private static ExecutionOptions Crossover( ExecutionOptions first, ExecutionOptions second) { var result = new ExecutionOptions { MinEstimation = Double.MinValue }; var props = typeof(ExecutionOptions) .GetProperties() .ToDictionary(p => p.Name); foreach (var variable in Variables) { var property = props[variable.Key]; double value = Random.Next(2) == 0 ? (double) property.GetValue(first) : (double) property.GetValue(second); //double firstValue = (double)property.GetValue(first); //double secondValue = (double)property.GetValue(second); //double mean = (firstValue + secondValue) / 2; property.SetValue(result, value); } return result; }
private static ExecutionResult Calculate(Snapshot snapshot, ExecutionOptions options) { var request = new ExecutionRequest { Snapshot = snapshot, Options = options }; var solver = new IterativeSearchSolver(1200); //new TraverseSolver(); return solver.Solve(request).First(); }
private static double SnapshotEvaluate(Snapshot snapshot, ExecutionOptions options) { if (snapshot.UnitHistory.Count <= 1) // new unit, so field has changed { snapshot.FieldEstimate = GetFieldEstimate(snapshot.Field, options); } return snapshot.Score + snapshot.FieldEstimate + GetUnitPositionBonus(snapshot.Field, snapshot.CurrentUnit, options); }
private static double GetUnitPositionBonus( Field field, Unit unit, ExecutionOptions options) { int minX = unit.GetMinX(); int maxX = unit.GetMaxX(); int minY = unit.GetMinY(); int maxY = unit.GetMaxY(); int depth = field.Height - minY; int width = maxX - maxY; int marginBottom = field.Height - maxY; int center = (maxX + minX) / 2; var attractor = GetBottomOpenPosition(field); double attractorDistance = Math.Abs(attractor.X - unit.Pivot.X); // attractor.DistanceTo(unit.Pivot); double depthPenalty = 0; foreach (var member in unit.Members) { depthPenalty += field.Height - 1 - member.Y; } int edgeBonus = 0; foreach (var position in unit.Members) { if (position.X == 0 || position.X == field.Width - 1) edgeBonus += 1; } double adjacencyBonus = GetAdjacencyBonus(field, unit, options); return edgeBonus * options.EdgeRatio + adjacencyBonus - depthPenalty * options.DepthPenaltyRatio - attractorDistance * options.AttractorRatio; }
private static double GetFieldEstimate(Field field, ExecutionOptions options) { return CornerCellsBonus(field) * options.CornerCellsBonus - GetHiddenHoles(field) * options.HiddenHolesPenalty; }