public string Generate(Board _board, GameUnit _unit, GameUnit _finishUnit) { var stringBuilder = new StringBuilder(); var words = MagicWordsStore.Words .Concat(SpecialWords) .ToArray(); var usedUnits = new HashSet<GameUnit>(); while (!_unit.Equals(_finishUnit)) { if (TimeLimiter.NeedStop()) break; foreach (var powerWord in words.OrderByDescending(x => x.Length)) { if (TimeLimiter.NeedStop()) break; var newlyUsedUnits = new HashSet<GameUnit>(); var currentUnit = _unit; var fail = false; for (var i = 0; i < powerWord.Length; ++i) { var command = powerWord[i]; newlyUsedUnits.Add(currentUnit); var nextUnit = currentUnit.MakeStep(CommandConverter.Convert(command)); var locked = !_board.IsValid(nextUnit); if (newlyUsedUnits.Contains(nextUnit) || usedUnits.Contains(nextUnit) || (locked && i < powerWord.Length - 1) || (locked && !nextUnit.Equals(_finishUnit))) { fail = true; break; } if (!locked) { currentUnit = nextUnit; } } var allUsedUnits = new HashSet<GameUnit>(usedUnits.Union(newlyUsedUnits)); if (!fail && ReachableStatesGetter.CanReach(_board, currentUnit, false, allUsedUnits, _finishUnit)) { _unit = currentUnit; usedUnits = allUsedUnits; stringBuilder.Append(powerWord); break; } } } foreach (var command in Enum.GetValues(typeof(Command)).Cast<Command>().Except(new[] { Command.Empty })) { if (!_board.IsValid(_unit.MakeStep(command))) { stringBuilder.Append(CommandConverter.CovertToAnyChar(command)); break; } } return stringBuilder.ToString(); }
public State(GameUnit unit, Command lastCommand, bool isLocked, bool canGoHorisontal, bool? isLastCommandWord) : this() { IsLocked = isLocked; Unit = unit; LastCommand = lastCommand; CanGoHorisontal = canGoHorisontal; IsLastCommandWord = isLastCommandWord; }
public static GameUnit[] Get(Board board, GameUnit unit, bool onlyLocked, HashSet<GameUnit> usedUnits = null) { var newlyUsedUnits = new HashSet<GameUnit>(); var lockedUnits = onlyLocked ? new HashSet<GameUnit>() : null; Dfs(board, unit, newlyUsedUnits, usedUnits ?? new HashSet<GameUnit>(), lockedUnits); return onlyLocked ? lockedUnits.ToArray() : newlyUsedUnits.ToArray(); }
public void TestBottomLeft() { var gameUnit = new GameUnit(Unit.Create(new Point(0, 0), new[] { new Point(0, 0), new Point(1, 0), new Point(2, 1), new Point(1, 1) }), new UnitPosition(new Point(0, 0), 0)); var actual = gameUnit.BottomLeft(); Assert.AreEqual(1, actual.Col); Assert.AreEqual(1, actual.Row); }
public GameUnit FindBest(GameUnit[] gameUnits, Game game) { return gameUnits.Select(x => new { Score = x.GetAbsolutePoints().Sum(point => point.Row*point.Row), GameUnit = x, BottomLeft = x.BottomLeft() }) .OrderByDescending(x => x.BottomLeft.Row) .ThenByDescending(x => x.Score) .ThenBy(x => x.BottomLeft.Col) .First() .GameUnit; }
public Game(Board board, GameUnit current, Unit[] unitsSequence, int currentUnitNumber, int lastUnitLinesCleared, int score, int problemId, long seed, string lastSymbols, int wordsMask) : this() { Board = board; Current = current; UnitsSequence = unitsSequence; CurrentUnitNumber = currentUnitNumber; LastUnitLinesCleared = lastUnitLinesCleared; Score = score; ProblemId = problemId; Seed = seed; LastSymbols = lastSymbols; WordsMask = wordsMask; }
public GameUnit FindBest(GameUnit[] positions, Game game) { var orderedPositions = positions .Select(x => new { GameUnit = x, Profit = GetScore(x.UnitPosition, game) }) .OrderByDescending(x => x.Profit.BusyRows) .ThenByDescending(x => x.Profit.DiverScore + x.Profit.ReachableCount + x.Profit.DensityScore); return orderedPositions .First() .GameUnit; }
public void TestGetPivotLocation3() { var game = new Game(Board.CreateEmpty(5, 7), null, null, 0, 0, 0, -1, -1, string.Empty, 0); var unit = Unit.Create(new Point(2, 4), new[] { new Point(2, 1), new Point(5, 1), new Point(1, 2), new Point(3, 2), new Point(4, 2), new Point(6, 2), new Point(7, 2), new Point(4, 3), new Point(5, 3), }); var actual = game.GetPivotLocation(unit); Assert.AreEqual(1, actual.Col); Assert.AreEqual(3, actual.Row); var gameUnit = new GameUnit(unit, new UnitPosition(actual, 0)); Assert.IsTrue(game.IsValid(gameUnit)); Console.WriteLine(game.Board.Place(gameUnit.GetAbsolutePoints()).ToString()); }
private static void Dfs(Board board, GameUnit unit, HashSet<GameUnit> newlyUsedUnits, HashSet<GameUnit> previouslyUsedUnits, HashSet<GameUnit> lockedUnits) { newlyUsedUnits.Add(unit); foreach (var command in Commands) { var nextUnit = unit.MakeStep(command); if (!previouslyUsedUnits.Contains(nextUnit) && !newlyUsedUnits.Contains(nextUnit)) { if (board.IsValid(nextUnit)) { Dfs(board, nextUnit, newlyUsedUnits, previouslyUsedUnits, lockedUnits); } else if (lockedUnits != null) { lockedUnits.Add(unit); } } } }
public void TestGet() { var board = Board.Create(new string[] { "...", "*.*", "..." }); var unit = Unit.Create(new Point(0, 0), new[] {new Point(0, 0), new Point(0, 1)}); var gameUnit = new GameUnit(unit, new UnitPosition(new Point(1, 0), 0)); var actual = ReachableStatesGetter.Get(board, gameUnit, false); CollectionAssert.AreEquivalent(new[] { new UnitPosition(new Point(1, 0), 0), new UnitPosition(new Point(1, 0), 5), new UnitPosition(new Point(0, 0), 5), new UnitPosition(new Point(1, 1), 0), new UnitPosition(new Point(1, 1), 1) }, actual.Select(x => x.UnitPosition)); }
private Profit GetScore(UnitPosition position, Game game) { var unit = game.Current.Unit; var points = new GameUnit(unit, position).GetAbsolutePoints(); var board = game.Board.Clone(); foreach (var point in points) { board.Fill(point); } var diverScore = 0; for (int i = 0; i < board.Height; i++) { for (int j = 0; j < board.Width; j++) { if (board.Field[i][j] == CellState.Busy) { diverScore += i * i; } } } var busyCount = 0; for (var i = 0; i < board.Height; i++) { if (board.Field[i].All(x => x == CellState.Busy)) { busyCount++; } } return new Profit { BusyRows = busyCount, DiverScore = diverScore, DensityScore = CalcDensity(board, points) }; }
private static bool Dfs2(Board board, GameUnit unit, HashSet<GameUnit> newlyUsedUnits, HashSet<GameUnit> previouslyUsedUnits, HashSet<GameUnit> lockedUnits, GameUnit finishUnit) { if (unit.Equals(finishUnit)) return true; newlyUsedUnits.Add(unit); foreach (var command in Commands) { var nextUnit = unit.MakeStep(command); if (!previouslyUsedUnits.Contains(nextUnit) && !newlyUsedUnits.Contains(nextUnit)) { if (board.IsValid(nextUnit) && Dfs2(board, nextUnit, newlyUsedUnits, previouslyUsedUnits, lockedUnits, finishUnit)) { return true; } else if (lockedUnits != null) { lockedUnits.Add(unit); } } } return false; }
public Game TrySpawnNew() { if (Current != null) { throw new Exception("Current unit is not null"); } if (CurrentUnitNumber == UnitsSequence.Length) { return GameOver(); } var unit = UnitsSequence[CurrentUnitNumber]; var pivot = GetPivotLocation(unit); var gameUnit = new GameUnit(unit, new UnitPosition(pivot, 0)); if (!IsValid(gameUnit)) { return GameOver(); } return SpawnedNew(gameUnit); }
private Game MoveCurrent(GameUnit gameUnit, string lastSymbols, int newScore, int wordsMask) { var clone = this; clone.Current = gameUnit; clone.State = GameState.Ok; clone.LastSymbols = lastSymbols; clone.Score = newScore; clone.WordsMask = wordsMask; return clone; }
private Game SpawnedNew(GameUnit gameUnit) { var clone = this; clone.Current = gameUnit; clone.State = GameState.NewIsSpawned; return clone; }
public bool IsValid(GameUnit gameUnit) { foreach (var point in gameUnit.GetAbsolutePoints()) { if (!InField(point)) { return false; } if (Field[point.Row][point.Col] == CellState.Busy) { return false; } } return true; }
public static bool CanReach(Board board, GameUnit unit, bool onlyLocked, HashSet<GameUnit> usedUnits, GameUnit finishUnit) { var newlyUsedUnits = new HashSet<GameUnit>(); var lockedUnits = onlyLocked ? new HashSet<GameUnit>() : null; return Dfs2(board, unit, newlyUsedUnits, usedUnits ?? new HashSet<GameUnit>(), lockedUnits, finishUnit); }
private bool CanMove(GameUnit unit, string word, out GameUnit nextUnit) { var tuple = new Tuple<GameUnit, string>(unit, word); if (moves.TryGetValue(tuple, out nextUnit)) { return nextUnit != null; } var gameUnits = new HashSet<GameUnit>(); gameUnits.Add(unit); nextUnit = unit; foreach (var command in word) { nextUnit = nextUnit.MakeStep(CommandConverter.Convert(command)); if (gameUnits.Contains(nextUnit) || !board.IsValid(nextUnit)) { moves[tuple] = null; return false; } gameUnits.Add(nextUnit); } moves[tuple] = nextUnit; return true; }
public string Generate(Board _board, GameUnit _unit, GameUnit _finishUnit) { board = _board; target = _finishUnit; moves = new Dictionary<Tuple<GameUnit, string>, GameUnit>(); words = MagicWordsStore.Words.Concat(SpecialWords).OrderByDescending(x => x.Length).ToArray(); dp = new Dictionary<State, DpInfo>(); var state = new State(_unit, Command.Empty, false, true, null); CalcDp(state); var stringBuilder = new StringBuilder(); while (!(state.Unit.Equals(target) && state.IsLocked)) { var dpInfo = dp[state]; stringBuilder.Append(dpInfo.Word); state = dpInfo.NextState.Value; } return stringBuilder.ToString(); }
public bool IsValid(GameUnit gameUnit) { return Board.IsValid(gameUnit); }