private static Tuple<double, Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[]> FindBestPositions_Recursive(int unitsAhead, Map map, Unit[] units, int unitIndex, string[] powerPhrases, bool[] spelledPhrases) { if (unitsAhead < 0 || unitIndex >= units.Length) { return Tuple.Create(0.0, new Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[0]); } var reachablePositions = new ReachablePositionsWithWords(map, powerPhrases, spelledPhrases); //var reachablePositions = new ReachablePositions(map); var evaluatePositions = new EvaluatePositions2(map); var unit = units[unitIndex]; var endPositions = reachablePositions.SingleEndPositions(unit); var estimated = new Dictionary<Unit, double>(); double? bestScore = null; var topOrderedPositions = endPositions .Select(p => { double value; if (estimated.TryGetValue(p.Item1, out value)) return Tuple.Create(value, p); var score = estimated[p.Item1] = evaluatePositions.Evaluate(p.Item1); return Tuple.Create(score, p); }) //.OrderByDescending(t => t.Item1) .OrderByDescending(t => (int)Math.Round(t.Item1 * 100)) .ThenByDescending(t => t.Item2.Item2.score) .TakeWhile(tt => { if (!bestScore.HasValue) { bestScore = tt.Item1; return true; } return Math.Abs(tt.Item1 - bestScore.Value) < 1e-6; }).ToList(); if (!topOrderedPositions.Any()) { return Tuple.Create(-1e3, new Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[0]); } var bestPosistions = Tuple.Create(double.MinValue, new Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[0]); foreach (var position in topOrderedPositions) { var newMap = map.Clone(); newMap.LockUnit(position.Item2.Item1); newMap.RemoveLines(); var nextPositions = FindBestPositions_Recursive(unitsAhead - 1, newMap, units, unitIndex + 1, powerPhrases, position.Item2.Item2.spelledWords); var score = position.Item1 + nextPositions.Item1; if (bestPosistions.Item1 < score) { bestPosistions = Tuple.Create(score, new[] {position.Item2}.Concat(nextPositions.Item2).ToArray()); } } return bestPosistions; }
private Tuple<double, Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[]> FindBestPositions_Recursive(int unitsAhead, Map map, Unit[] units, int unitIndex, string[] powerPhrases, bool[] spelledPhrases) { if (unitsAhead < 0 || unitIndex >= units.Length) { return Tuple.Create(0.0, new Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[0]); } var reachablePositions = new ReachablePositionsWithWords(map, powerPhrases, spelledPhrases); //var reachablePositions = new ReachablePositions(map); // var evaluatePositions = new EvaluatePositions(map); var evaluatePositions = new EvaluatePositions2(map); var unit = units[unitIndex]; var endPositions = reachablePositions.SingleEndPositions(unit); var estimated = new Dictionary<Unit, double>(); var topOrderedPositions = endPositions .Select(p => { double value; if (estimated.TryGetValue(p.Item1, out value)) return Tuple.Create(value, p); var score = estimated[p.Item1] = evaluatePositions.Evaluate(p.Item1); return Tuple.Create(score, p); }) //.OrderByDescending(t => t.Item1) .OrderByDescending(t => (int)Math.Round(t.Item1 * 100) + t.Item2.Item2.score) .ToList(); var equallyTop = GetEquallyGoodTop(topOrderedPositions); var positionsForLookingAhead = topOrderedPositions.Take(Math.Max(equallyTop, minTopUnitCount)).ToList(); if (!positionsForLookingAhead.Any()) { return Tuple.Create(-1e3, new Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[0]); } var bestPosistions = Tuple.Create(double.MinValue, new Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[0]); foreach (var position in positionsForLookingAhead) { var newMap = map.Clone(); newMap.LockUnit(position.Item2.Item1); newMap.RemoveLines(); var nextPositions = FindBestPositions_Recursive(unitsAhead - 1, newMap, units, unitIndex + 1, powerPhrases, position.Item2.Item2.spelledWords); var score = position.Item1 + nextPositions.Item1; if (bestPosistions.Item1 < score) { bestPosistions = Tuple.Create(score, new[] {position.Item2}.Concat(nextPositions.Item2).ToArray()); } } return bestPosistions; }