public static IEnumerable<OracleSuggestion> GetReachableSugessions(IFinder finder, Map map) { return finder.GetReachablePositions(map) .Select(m => TryGetSugession(m, m.Unit)) .Where(s => s != null); }
private void Dfs(Map map, List<Directions> history) { var maxPrefixForDir = new Tuple<int, int>[dirs.Length]; for (int i = 0; i < dirs.Length; i++) maxPrefixForDir[i] = Tuple.Create(-1, i); for (int i = 0; i < 1; i++) { var directions = phrases.AsDirections[i]; for (int j = Math.Min(directions.Length - 1, history.Count); j >= 0; j--) { bool eq = true; for (int k = 0; k < j && eq; k++) if (directions[k] != history[history.Count - j + k]) eq = false; if (eq && map.IsGoodPath(directions.Skip(j))) { int index = (int)directions[j]; var pair = maxPrefixForDir[index]; if (j >= pair.Item1) maxPrefixForDir[index] = Tuple.Create(j, pair.Item2); break; } } } var dirsOrder = Enumerable.Range(0, dirs.Length).OrderByDescending(i => maxPrefixForDir[i]); foreach (var d in dirsOrder) DfsStep(map, (Directions)d, history); }
public OracleSuggestion(UnitPosition position, Directions lockingDirection, Map lockedFinalMap, double metrics = 0) { Position = position; LockingDirection = lockingDirection; this.LockedFinalMap = lockedFinalMap; Metrics = metrics; }
public Tuple<int, IEnumerable<Directions>> GetSpellLengthAndPath(Map map, UnitPosition target) { UpdateMap(map); var path = !Parents.ContainsKey(target) ? null : RestoreDirections(target).Reverse(); return Tuple.Create(0, path); //TODO not zero! }
public static double Check(Map before, Map after, PositionedUnit unit) { if (!before.NextUnits.Any(z => z.IsLine)) return 0; if (CheckLayerFillness(before,0,2*before.Height/3) > 0.01) return 0; var any = unit.Members.Any(p => AtLine(before, p)); var all = unit.Members.All(p => AtLine(before, p)); if (!unit.Unit.IsLine) { if (any) return -1; return 0; } else { if (all) { if (CheckReadinessForLine(before) < unit.Members.Count()) return -1; return 1; } else if (any) return -1; else return 0; } }
public static double Minimize(Map before, Map after, PositionedUnit unit) { var xmin = Math.Max(0, unit.Rectangle.X - 2); var xmax = Math.Min(before.Width, unit.Rectangle.Right + 2); var ymin = Math.Max(0, unit.Rectangle.Y - 2); var ymax = Math.Min(before.Height, unit.Rectangle.Bottom + 2); var dict = new Dictionary<int, int>(); for (int i = -4; i <= 4; i++) dict[i] = 0; for(int x= xmin;x< xmax;x++) for (int y= ymin;y<ymax;y++) { var delta = FindClosureIndex(x, y, after) - FindClosureIndex(x, y, before); dict[delta]++; } double factor = 1; double result = 0; for (int i = 4; i > 0; i--) { result -= dict[i] * factor; result += dict[-i] * factor; factor /= 2; } return result; }
private static OracleSuggestion TryGetSugession(Map map, PositionedUnit unit) { return GetAllDirections() .Where(dir => !map.IsValidPosition(unit.Move(dir))) .Select(dir => new OracleSuggestion(unit.Position, dir, map.LockUnit())) .FirstOrDefault(); }
public static double EraseLines(Map before, Map after, PositionedUnit unit) { if (after.Scores.ClearedLinesCountAtThisMap == 0) return 0; if (after.Scores.ClearedLinesCountAtThisMap == 1) return 0.3; if (after.Scores.ClearedLinesCountAtThisMap == 2) return 0.8; return 1; }
public static double Maximize(Map before, Map after, PositionedUnit unit) { var beforeIndex = FindLinearityIndex(before); var afterIndex = FindLinearityIndex(after); if (afterIndex < beforeIndex) return 0; if (beforeIndex < 0.01) return 1; return Math.Min(afterIndex / beforeIndex, 1); }
public static double CheckLayerFillness(Map map, int fromY, int ycount) { double filledCellsCount = 0; for (int y = fromY; y < fromY+ycount; y++) for (int x = 0; x < map.Width; x++) filledCellsCount += map.Filled[x, y] ? 1 : 0; return filledCellsCount / (map.Width * ycount); }
private Tuple<double, Map> Evaluate(int depth, Map map, double metricValue) { if (depth == lookupDepth) return Tuple.Create(map.Scores.TotalScores + metricValue, map); if (map.IsOver) return Tuple.Create(map.Scores.TotalScores + 0.0, map); var bestMap = EvaluateSuggestions(depth, map).MaxItem(z => z.Metrics); return Tuple.Create(bestMap.Metrics, bestMap.LockedFinalMap); }
public static bool AtLine(Map map, Point p) { var end = new Point(map.Width/2, map.Height - 1); var dp = end.Sub(p); if ( end.Y % 2 == 0) return dp.X == (dp.Y + 1) / 2; else return dp.X == dp.Y / 2; }
public static OracleSuggestion Evaluate(this IEnumerable<WeightedMetric> metrics, Map before, OracleSuggestion suggestions) { var unit = new PositionedUnit(before.Unit.Unit, suggestions.Position); var after = before.TeleportUnit(suggestions.Position).LockUnit(); return new OracleSuggestion( suggestions.Position, suggestions.LockingDirection, after, metrics.Evaluate(before, after, unit)); }
public static int CheckReadinessForLine(Map map) { for (int y=map.Height-1;y>=0;y--) { for (int x = 0; x < map.Width; x++) if (map.Filled[x, y] == AtLine(map, new Point(x, y))) return map.Height - 1 - y; } return map.Height - 1; }
private void DfsStep(Map map, Directions d, List<Directions> history) { if (!map.IsSafeMovement(d)) return; var newMap = map.Move(d); var pos = newMap.Unit.Position; if (Parents.ContainsKey(pos)) return; Parents.Add(pos, Tuple.Create(map, d)); history.Add(d); Dfs(newMap, history); history.RemoveAt(history.Count - 1); }
public Tuple<string, Map> ResultAsTuple(Map map) { var result = ""; while (!map.IsOver) { var dirs = MakeMove(map).ToList(); result += dirs.ToPhrase(); map = dirs.Aggregate(map, (m, dir) => m.Move(dir)); } return Tuple.Create(result, map); }
public static IEnumerable<UnitPosition> GetAllUnitPositions(Map map) { for (var x = 0; x < map.Width; x++) { for (var y = 0; y < map.Height; y++) { for (var rot = 0; rot < map.Unit.Unit.Period; rot++) yield return new UnitPosition {Angle = rot, Point = new Point(x, y)}; } } }
static double Run(Map map, List<WeightedMetric> metric) { var phrases = new Phrases(Phrases.DefaultPowerWords); var finder = new MagicDfsFinder(phrases); var mephala = new MephalaOracle(finder, metric); var solver = new Solver(phrases, finder, mephala); // Console.Write("Solving "); //Console.WriteLine(argument.Code.Select(z => Math.Round(z, 3).ToString()).Aggregate((a, b) => a + " " + b)); var result = solver.Solve(map); //Console.WriteLine("Result" + result.Score + "\n\n"); return result.Score; }
public static double Index(Map _, Map map, PositionedUnit unit) { var bads = from x in Enumerable.Range(0, map.Width) from y in Enumerable.Range(0, map.Height) where !map.Filled[x, y] let cap = GetSmallCap(x, y).Where(map.IsInside) let capSize = cap.Count() let filledCapSize = cap.Count(p => map.Filled[p.X, p.Y]) select CapPenalty(filledCapSize, capSize, x == 0 || x == map.Width-1); double max = map.Width * map.Height; return (max - bads.Sum()) / max; }
public IEnumerable<OracleSuggestion> EvaluateSuggestions(int depth, Map map) { var suggestions = OracleServices .GetReachableSugessions(finder, map) .Select(suggestion => metric.Evaluate(map, suggestion)) .OrderByDescending(z => z.Metrics) .Take(Math.Max(2, lookupWidth - depth)) .ToList(); return from s in suggestions let evaluatedFinalMap = Evaluate(depth + 1, s.LockedFinalMap, s.Metrics) select new OracleSuggestion( s.Position, s.LockingDirection, evaluatedFinalMap.Item2, evaluatedFinalMap.Item1); }
static double FindLinearityIndex(Map map) { int count = 0; double sum = 0; for (int y = 0; y < map.Height; y++) for (int x = 0; x < map.Width; x++) { if (map.Filled[x, y]) continue; var length = ResultingLength( GetPathLength(map, x, y, Directions.E), GetPathLength(map, x, y, Directions.SE), GetPathLength(map, x, y, Directions.SW)); if (length < 0) continue; sum += length; count++; } return sum / count; }
public Tuple<int, IEnumerable<Directions>> GetSpellLengthAndPath(Map map, UnitPosition target) { Tuple<int, IEnumerable<Directions>> best = null; int bestCost = -1; foreach (var sequence in GenerateSpellsSequences()) { var midPositions = new UnitPosition[sequence.Count]; var finish = target; for (int i = 0; i < sequence.Count; i++) midPositions[i] = finish = GetMidPositionByPhrase(finish, sequence[i], map.Unit.Unit.Period); var path = dfsFinder.GetSpellLengthAndPath(map, finish); if (path?.Item2 == null) continue; var maps = midPositions.Select(p => new Map(map.Id, map.Filled, new PositionedUnit(map.Unit.Unit, p), map.NextUnits, map.UsedPositions, map.Scores)).ToArray(); bool ok = true; for (int i = 0; i < sequence.Count && ok; i++) ok &= maps[i].IsGoodPath(sequence[i]); if (!ok) continue; var result = path.Item2.Concat(((IEnumerable<Directions[]>)sequence).Reverse().SelectMany(s => s)).ToArray(); if (map.IsGoodPath(result)) { if (!ChooseCarefully) return Tuple.Create<int, IEnumerable<Directions>>(0, result); var originalPhrase = phrases.ToOriginalPhrase(result.ToPhrase()); int cost = phrases.GetPowerScoreWithoutUniqueBonus(originalPhrase); if (cost > bestCost) { bestCost = cost; best = Tuple.Create<int, IEnumerable<Directions>>(0, result); } } } if (best == null) best = dfsFinder.GetSpellLengthAndPath(map, target); return best; }
public List<Directions> MakeMove(Map map) { var suggestions = Oracle.GetSuggestions(map).ToList(); log.Info(map.Scores); // LogSugessions("all", suggestions); if (suggestions.Count == 0) return null; var bestMetric = suggestions[0].Metrics; var selectedSugessions = suggestions .Take(bestSugessionsCount) .Where(s => s.Metrics >= bestMetric * metricEpsilon).ToList(); // LogSugessions("selected", selectedSugessions); var sugestionsWithPaths = from s in selectedSugessions let path = GetPath(map, s).ToList() let phrase = path.ToPhrase() let powerScore = phrases.GetPowerScore(phrases.ToOriginalPhrase(phrase)) select new {s, path, phrase, powerScore}; var theOne = sugestionsWithPaths.MaxItem(s => s.powerScore); // log.Info($"SelectedMove: {theOne.powerScore} {theOne.phrase}\r\n*{theOne.s} -> \r\n{theOne.s.LockedFinalMap}"); return theOne.path; }
public IEnumerable<OracleSuggestion> GetSuggestions(Map map) { var finalMaps = finder.GetReachablePositions(map); var suggestions = new List<OracleSuggestion>(); foreach (var finalMap in finalMaps) { var positionedUnit = finalMap.Unit; var lockedMap = finalMap.LockUnit(); foreach (var dir in OracleServices.GetAllDirections()) { if (!finalMap.IsValidPosition(positionedUnit.Move(dir))) { var m = metrics.Sum(z => z.Function(map,lockedMap, positionedUnit) * z.Weight); suggestions.Add(new OracleSuggestion(finalMap.Unit.Position, dir, lockedMap, m)); break; } } } return suggestions.OrderByDescending(s => s.Metrics); }
public static double ShouldNotCreateSimpleHoles(Map before, Map after, PositionedUnit unit) { var score = unit.Members.Max(m => m.Y) // чем ниже нижняя точка, тем лучше + unit.Members.Average(m => m.Y) / 10.0 // чем ниже центр масс, тем лучше + unit.Members.Max(m => m.X)*0.2 / after.Width; // лучше двигать фигуры в одну сторону при прочих равных, а не кидать посередине // последний коэффициент при maxX подобран несколькими запусками ArensTests. // остальные выбраны наобум. if (after.Scores.ClearedLinesCountAtThisMap > 0) return score + 100; for (int i = -1; i < unit.Rectangle.Width + 1; i++) { for (int j = -1; j < unit.Rectangle.Height + 1; j++) { var point = new Point(unit.Rectangle.X + i, unit.Rectangle.Y + j); if(point.X.InRange(0, after.Width - 1) && (point.Y.InRange(0, after.Height - 1) && after.IsSimpleHole(point))) return score - 3; // за дырку штраф эквивалентный трем позициям по Y. } } return score; }
public SolverResult Solve(Map map) { if (map.Width * map.Height > 50 * 50) { return fastest.Solve(map); } var sw = Stopwatch.StartNew(); var res = fast.Solve(map); if (sw.Elapsed.TotalSeconds < 10) { var res2 = fast2.Solve(map); if (res2.Score > res.Score) res = res2; } if (sw.Elapsed.TotalSeconds < 10 && IsSmall(map)) { var solver = IsSmallest(map) ? slowest : slow; var res2 = solver.Solve(map); if (res2.Score > res.Score) return res2; } return res; }
public IEnumerable<OracleSuggestion> GetSuggestions(Map map) { return EvaluateSuggestions(0, map).OrderByDescending(z => z.Metrics); }
public static double Evaluate(this IEnumerable<WeightedMetric> metrics, Map before, Map after, PositionedUnit unit) { return metrics.Sum(z => z.Function(before, after, unit) * z.Weight); }
public double Estimate(Map map, PositionedUnit unit) { return 42; }
public static IEnumerable<Directions> GetPath(this IFinder finder, Map map, UnitPosition target) { return finder.GetSpellLengthAndPath(map, target).Item2; }