public void GetCells() { var u = new Unit(new[] {new Cell(0, 0), new Cell(1, 0), new Cell(1, 1)}, new Cell(0, 0)); var us = new UnitState(new Cell(2, 2), 0); var cells = us.GetCells(u); Assert.IsTrue(cells.Contains(new Cell(2, 2))); Assert.IsTrue(cells.Contains(new Cell(3, 2))); Assert.IsTrue(cells.Contains(new Cell(3, 3))); us = new UnitState(new Cell(2, 2), 1); cells = us.GetCells(u); Assert.IsTrue(cells.Contains(new Cell(2, 2))); Assert.IsTrue(cells.Contains(new Cell(2, 1))); Assert.IsTrue(cells.Contains(new Cell(3, 1))); us = new UnitState(new Cell(2, 3), 0); cells = us.GetCells(u); Assert.IsTrue(cells.Contains(new Cell(2, 3))); Assert.IsTrue(cells.Contains(new Cell(3, 3))); Assert.IsTrue(cells.Contains(new Cell(4, 4))); u = new Unit(new[] { new Cell(0, 1), new Cell(1, 1), new Cell(2, 2) }, new Cell(0, 1)); us = new UnitState(new Cell(2, 2), 0); cells = us.GetCells(u); Assert.IsTrue(cells.Contains(new Cell(2, 2))); Assert.IsTrue(cells.Contains(new Cell(3, 2))); Assert.IsTrue(cells.Contains(new Cell(3, 3))); }
public PhraseCombineInfo(PowerPhraseData pd, PowerPhraseInfo p1, PowerPhraseInfo p2, CombineType combineType, PhraseMetricType metricType) { PrevPhrase = p1; NextPhrase = p2; this.CombineType = combineType; IntersectionLen = CalcIntersectionLen(p1.Phrase, p2.Phrase); if (combineType == CombineType.Overlap && IntersectionLen == 0) throw new Exception(); CommandsStr = p2.Phrase.Substring(IntersectionLen); var fakeUnitState = new UnitState(new Cell(0, 0), 0); Commands = MovesPrinter.GetCommands(CommandsStr); MinX = 0; MaxX = 0; foreach (var cmd in Commands) { fakeUnitState = UnitState.MoveFuncs[cmd](fakeUnitState); MinX = Math.Min(MinX, fakeUnitState.Pivot.x); MaxX = Math.Max(MaxX, fakeUnitState.Pivot.x); } DY = fakeUnitState.Pivot.y; switch (combineType) { case CombineType.Overlap: EffectiveLen = pd.CalcEffectiveLen(p1.Phrase + CommandsStr) - p1.EffectiveLength; break; case CombineType.Append: EffectiveLen = p2.EffectiveLength; break; case CombineType.MoveDownAppend: EffectiveLen = p2.EffectiveLength; ++DY; break; } switch (metricType) { case PhraseMetricType.Div: Metric = (double)EffectiveLen / DY; break; case PhraseMetricType.Diff: Metric = (double)EffectiveLen - DY; break; case PhraseMetricType.Div2: Metric = (double)EffectiveLen / (DY + LAST_MOVE_PENALTY[Commands[Commands.Length - 1]]); break; case PhraseMetricType.Div3: Metric = (double)EffectiveLen / (DY + LAST_MOVE_PENALTY[Commands[Commands.Length - 1]] * 2); break; default: throw new ArgumentOutOfRangeException("metricType"); } DebugPrinter.WriteLine("Phrase combine: \"{0}\" and \"{1}\" with type {2}, effective len {3}, DY {4}, metric {5}", p1.Phrase, p2.Phrase, combineType, EffectiveLen, DY, Metric); }
public IEnumerable<BfsState> DoBfs(UnitState startState, PowerPhraseInfo[] powerPhrases) { var queue = new Queue<BfsState>(); Debug.Assert(startState.GetCells(_unit).All(_field.IsValidCell)); _visited[startState] = new VisitInfo { MoveFuncIndex = -1, PrevState = null, AllPrevStates = new HashSet<UnitState>(), }; var startBfsState = new BfsState(startState, startState.GetCells(_unit)); //BfsState stateAfterPhrase = startBfsState; //if (powerPhrases != null) //{ // foreach (var phraseInfo in powerPhrases) // { // stateAfterPhrase = ApplyPhraseManyTimes(startBfsState, phraseInfo); // if (stateAfterPhrase.UnitState.Pivot != startState.Pivot || stateAfterPhrase.UnitState.Rotation != startState.Rotation) // break; // } //} var stateAfterPhrase = ApplyManyPhrasesManyTimes(startBfsState); queue.Enqueue(stateAfterPhrase); while (queue.Count > 0) { var state = queue.Dequeue(); int blockingMove = -1; for (int funcIndex = 0; funcIndex < UnitState.MoveFuncs.Length; ++funcIndex) { UnitState newUnitState = UnitState.MoveFuncs[funcIndex](state.UnitState); Cell[] cells; bool isBlocking; if (!TryAddVisitedState(newUnitState, state.UnitState, funcIndex, out cells, out isBlocking)) { if (isBlocking) blockingMove = funcIndex; continue; } queue.Enqueue(new BfsState(newUnitState, cells)); } if (blockingMove >= 0) { state.BlockingMove = blockingMove; yield return state; } } }
public IEnumerable<BfsState> DoSimpleBfs(UnitState startState, bool backwards, bool returnStateCopies) { var queue = new Queue<UnitState>(); Debug.Assert(startState.GetCells(_unit).All(_field.IsValidCell)); _visited[startState] = new VisitInfo { MoveFuncIndex = -1, PrevState = null, AllPrevStates = new HashSet<UnitState>(), }; queue.Enqueue(startState); var moveFuncs = backwards ? UnitState.BackMoveFuncs : UnitState.MoveFuncs; BfsState returnState = new BfsState(null, null); while (queue.Count > 0) { var state = queue.Dequeue(); int blockingMove = -1; for (int funcIndex = 0; funcIndex < moveFuncs.Length; ++funcIndex) { UnitState newUnitState = moveFuncs[funcIndex](state); newUnitState.Normalize(_unit); Cell[] cells; bool isBlocking; if (!TryAddVisitedState(newUnitState, state, funcIndex, out cells, out isBlocking)) { if (isBlocking) blockingMove = funcIndex; continue; } queue.Enqueue(newUnitState); } if (blockingMove >= 0 || backwards) { if (returnStateCopies) { var retState = new BfsState(state, state.GetCells(_unit)); retState.BlockingMove = blockingMove; yield return retState; } else { returnState.UnitState = state; yield return returnState; } } } }
public void MoveE() { var unit = new Unit(new[] { new Cell(10, 0), new Cell(11, 1) }, new Cell(12, 2)); var unitState = new UnitState(unit.pivot, 0); unitState = UnitState.MoveE(unitState); var cells = unitState.GetCells(unit); Assert.IsTrue(cells.Contains(new Cell(11, 0))); Assert.IsTrue(cells.Contains(new Cell(12, 1))); Assert.AreEqual(new Cell(13, 2), unitState.Pivot); }
public void MoveSW() { var unit = new Unit(new[] { new Cell(10, 4), new Cell(11, 5) }, new Cell(12, 6)); var unitState = new UnitState(unit.pivot, 0); unitState = UnitState.MoveSW(unitState); var cells = unitState.GetCells(unit); Assert.AreEqual(2, cells.Length); Assert.IsTrue(cells.Contains(new Cell(9, 5))); Assert.IsTrue(cells.Contains(new Cell(11, 6))); Assert.AreEqual(new Cell(11, 7), unitState.Pivot); }
public void TestConstructor() { var f = new Field(3, 3, new Cell(0, 1), new Cell(2, 1)); var us = new UnitState(new Cell(0, 0), 0); var u = new Unit(new[] {new Cell(0, 0)}, new Cell(0, 0)); var bfss = new BestStateInfo(f, u, new BfsState(us, new Cell(0, 2))); Assert.AreEqual(0, bfss.KilledRows); Assert.AreEqual(5, bfss.JoinedCellsCount); Assert.AreEqual(0, bfss.NewHolesCount); bfss = new BestStateInfo(f, u, new BfsState(us, new Cell(1, 1))); Assert.AreEqual(1, bfss.KilledRows); Assert.AreEqual(2, bfss.JoinedCellsCount); Assert.AreEqual(1, bfss.NewHolesCount); bfss = new BestStateInfo(f, u, new BfsState(us, new Cell(1, 1), new Cell(0, 2), new Cell(1, 2), new Cell(2, 2))); Assert.AreEqual(2, bfss.KilledRows); Assert.AreEqual(9, bfss.JoinedCellsCount); Assert.AreEqual(0, bfss.NewHolesCount); bfss = new BestStateInfo(f, u, new BfsState(us, new Cell(1, 2))); Assert.AreEqual(0, bfss.KilledRows); Assert.AreEqual(3, bfss.JoinedCellsCount); Assert.AreEqual(1, bfss.NewHolesCount); bfss = new BestStateInfo(f, u, new BfsState(us, new Cell(0, 0), new Cell(1, 0), new Cell(1, 1), new Cell(1, 2))); Assert.AreEqual(1, bfss.KilledRows); Assert.AreEqual(6, bfss.JoinedCellsCount); Assert.AreEqual(2, bfss.NewHolesCount); f = new Field(3, 3, new Cell(0, 1)); bfss = new BestStateInfo(f, u, new BfsState(us, new Cell(1, 2), new Cell(1, 1), new Cell(2, 0))); Assert.AreEqual(0, bfss.KilledRows); Assert.AreEqual(4, bfss.JoinedCellsCount); Assert.AreEqual(2, bfss.NewHolesCount); f = new Field(4, 4, new Cell(0, 3), new Cell(1, 3), new Cell(2, 3)); bfss = new BestStateInfo(f, u, new BfsState(us, new Cell(0, 0), new Cell(0, 1), new Cell(1, 1), new Cell(0, 2), new Cell(2, 2))); Assert.AreEqual(0, bfss.KilledRows); Assert.AreEqual(7, bfss.JoinedCellsCount); Assert.AreEqual(1, bfss.NewHolesCount); }
public UnitState SpawnUnit(Unit unit) { int ymin = unit.members[0].y; foreach (var cell in unit.members) if (cell.y < ymin) ymin = cell.y; var us = new UnitState(new Cell(unit.pivot.x, unit.pivot.y - ymin), 0); var cells = us.GetCells(unit); int xmin = cells[0].x, xmax = cells[0].x; foreach (var cell in cells) { if (cell.x < xmin) xmin = cell.x; if (cell.x > xmax) xmax = cell.x; } int x0 = (Width - 1 - (xmax - xmin)) / 2; us = new UnitState(new Cell(us.Pivot.x - xmin + x0, us.Pivot.y), 0); foreach (var cell in us.GetCells(unit)) if (!IsValidCell(cell)) return null; us.Normalize(unit); return us; }
public void TurnCounter() { var unit = new Unit(new[] { new Cell(3, 0) }, new Cell(2, 3)); var unitState = new UnitState(unit.pivot, 0); unitState = UnitState.TurnCounter(unitState); var cells = unitState.GetCells(unit); Assert.AreEqual(3, unitState.Pivot.y); Assert.AreEqual(2, unitState.Pivot.x); Assert.AreEqual(1, cells[0].y); Assert.AreEqual(0, cells[0].x); unitState = UnitState.TurnCounter(unitState); Assert.AreEqual(new Cell(0, 4), unitState.GetCells(unit)[0]); unitState = UnitState.TurnCounter(unitState); Assert.AreEqual(new Cell(2, 6), unitState.GetCells(unit)[0]); unitState = UnitState.TurnCounter(unitState); Assert.AreEqual(new Cell(4, 5), unitState.GetCells(unit)[0]); unitState = UnitState.TurnCounter(unitState); Assert.AreEqual(new Cell(5, 2), unitState.GetCells(unit)[0]); unit = new Unit(new[] { new Cell(0, 2), new Cell(4, 2) }, new Cell(2, 2)); unitState = new UnitState(unit.pivot, 0); unitState = UnitState.TurnCounter(unitState); cells = unitState.GetCells(unit); Assert.IsTrue(cells.Contains(new Cell(1, 4))); Assert.IsTrue(cells.Contains(new Cell(3, 0))); unitState = UnitState.TurnCounter(unitState); cells = unitState.GetCells(unit); Assert.IsTrue(cells.Contains(new Cell(3, 4))); Assert.IsTrue(cells.Contains(new Cell(1, 0))); }
private bool _IsReachable(UnitState unitState, UnitState finalState, out List<int> reversedPathIfSuccess) { var oldVisited = new Dictionary<UnitState, VisitInfo>(_visited); bool reachable = false; reversedPathIfSuccess = null; foreach (var bfsState in DoSimpleBfs(unitState, false, false)) { if (bfsState.UnitState == finalState) { reachable = true; reversedPathIfSuccess = GetMoves(finalState, unitState, true); break; } } _visited = oldVisited; return reachable; }
public List<int> GetMoves(UnitState finalState, UnitState startState, bool reversed = false) { var moves = new List<int>(); UnitState state = finalState; while (state != startState) { var visitedInfo = _visited[state]; moves.Add(visitedInfo.MoveFuncIndex); state = visitedInfo.PrevState; } if (!reversed) moves.Reverse(); return moves; }
private bool _IsDuplicateState(UnitState prevState, UnitState newState) { int newCanonicalRotation = _unit.GetCanonicalRotation(newState.Rotation); //return _visited[prevState].AllPrevStates.Contains(new UnitState(newState.Pivot, newCanonicalRotation)); while (prevState != null) { if (newState.Pivot == prevState.Pivot && newCanonicalRotation == _unit.GetCanonicalRotation(prevState.Rotation)) return true; Debug.Assert(_visited.ContainsKey(prevState)); prevState = _visited[prevState].PrevState; } return false; }
private bool TryAddVisitedState(UnitState newState, UnitState state, int funcIndex, out Cell[] cells, out bool isBlockingMove, char moveChar = ANY_CHAR) { cells = null; isBlockingMove = false; if (_visited.ContainsKey(newState)) return false; cells = newState.GetCells(_unit); if (!cells.All(_field.IsValidCell)) { isBlockingMove = true; return false; } //if (_IsDuplicateState(state, newState)) // return false; var vi = new VisitInfo { MoveFuncIndex = funcIndex, PrevState = state, MoveChar = moveChar, //AllPrevStates = _visited[state].AllPrevStates // AllPrevStates = new HashSet<UnitState>(_visited[state].AllPrevStates) }; // vi.AllPrevStates.Add(new UnitState(state.Pivot, _unit.GetCanonicalRotation(state.Rotation))); _visited[newState] = vi; return true; }
public static UnitState TurnClockwise(UnitState state) { return new UnitState(state.Pivot, (state.Rotation + 5) % 6); }
protected bool Equals(UnitState other) { return Pivot.Equals(other.Pivot) && Rotation == other.Rotation; }
public void ReachStateUsingPhrases(UnitState startState, UnitState finalState) { var backBfs = new BFS2(_field, _unit, _gameData); #if false// DEBUG DebugPrinter.WriteLine("Checking what is reachable back from: ({0}, {1}) rot {2}", finalState.Pivot.x, finalState.Pivot.y, finalState.Rotation); var reachableArr = backBfs.DoSimpleBfs(finalState, true).Select(st => st.UnitState).ToArray(); foreach (var st in reachableArr) DebugPrinter.WriteLine(" reachable: ({0}, {1}) rot {2}", st.Pivot.x, st.Pivot.y, st.Rotation); var reachableStates = new HashSet<UnitState>(reachableArr); #else var reachableStates = new HashSet<UnitState>(backBfs.DoSimpleBfs(finalState, true, false).Select(st => st.UnitState)); #endif _visited[startState] = new VisitInfo { MoveFuncIndex = -1, PrevState = null, AllPrevStates = new HashSet<UnitState>(), }; UnitState curState = startState; PowerPhraseInfo prevPhrase = _gameData.PowerPhraseData.Phrases[0]; // empty phrase List<int> curReversedPath = null; while (curState != finalState) { UnitState stateAfterPhrase; PowerPhraseInfo appliedPhrase; List<int> reversedPathAfterPhrase; var prevState = curState; bool phraseApplied = ApplySomePhrase(curState, prevPhrase, reachableStates, finalState, out stateAfterPhrase, out appliedPhrase, out reversedPathAfterPhrase); curState = stateAfterPhrase; if (phraseApplied) { //movesStr += appliedPhrase.Phrase; curReversedPath = reversedPathAfterPhrase; prevPhrase = appliedPhrase; continue; } prevPhrase = _gameData.PowerPhraseData.Phrases[0]; // Do BFS step if (curReversedPath == null) { bool reachable = _IsReachable(curState, finalState, out curReversedPath); Debug.Assert(reachable); } int move = curReversedPath[curReversedPath.Count - 1]; var state = curState; curState = UnitState.MoveFuncs[move](curState); curState.Normalize(_unit); curReversedPath.RemoveAt(curReversedPath.Count - 1); _visited[curState] = new VisitInfo { MoveFuncIndex = move, PrevState = state, MoveChar = ANY_CHAR, }; } }
public void MoveW() { var unit = new Unit(new[] { new Cell(10, 0), new Cell(11, 0) }, new Cell(12, 0)); var unitState = new UnitState(unit.pivot, 0); unitState = UnitState.MoveW(unitState); var cells = unitState.GetCells(unit); Assert.IsTrue(cells.Contains(new Cell(9, 0))); Assert.IsTrue(cells.Contains(new Cell(10, 0))); }
public Dictionary<Cell, char> GetPathCells(UnitState finalState) { var cells = new Dictionary<Cell, char>(); UnitState state = finalState; while (state != null) { var visitedInfo = _visited[state]; cells[state.Pivot] = _visited[state].MoveChar; state = visitedInfo.PrevState; if (state == null) break; } return cells; }
public string GetMovesString(UnitState finalState) { var moves = ""; UnitState state = finalState; while (state != null) { var visitedInfo = _visited[state]; state = visitedInfo.PrevState; if (state == null) break; if (visitedInfo.MoveChar == ANY_CHAR) moves = MovesPrinter.PrintOneMove(visitedInfo.MoveFuncIndex) + moves; else moves = visitedInfo.MoveChar + moves; } return moves; }
public List<int> GetMoves(UnitState finalState) { var moves = new List<int>(); UnitState state = finalState; while (state != null) { var visitedInfo = _visited[state]; state = visitedInfo.PrevState; if (state != null) moves.Add(visitedInfo.MoveFuncIndex); } moves.Reverse(); return moves; }
public PowerPhraseInfo(string phrase, int index) { Phrase = phrase; Index = index; Commands = MovesPrinter.GetCommands(phrase); var visited = new HashSet<Cell>(); var fakeUnitState = new UnitState(new Cell(0, 0), 0); MinX = 0; MaxX = 0; HasRotations = false; foreach (var cmd in Commands) { fakeUnitState = UnitState.MoveFuncs[cmd](fakeUnitState); MinX = Math.Min(MinX, fakeUnitState.Pivot.x); MaxX = Math.Max(MaxX, fakeUnitState.Pivot.x); HasRotations |= (cmd >= 4); visited.Add(fakeUnitState.Pivot); } DY = fakeUnitState.Pivot.y; // try to repeat CanRepeatImmediately = true; foreach (var cmd in Commands) { fakeUnitState = UnitState.MoveFuncs[cmd](fakeUnitState); if (visited.Contains(fakeUnitState.Pivot)) { CanRepeatImmediately = false; break; } } }
public BfsState(UnitState unitState, params Cell[] cells) { UnitState = unitState; Cells = cells; BlockingMove = -1; }
private UnitState ApplyPhrase(UnitState startState, string commandsStr, int[] cmd) { Debug.Assert(commandsStr.Length == cmd.Length); var state = startState; for (int cmdIndex = 0; cmdIndex < cmd.Length; ++cmdIndex) { bool dummy; var nextState = UnitState.MoveFuncs[cmd[cmdIndex]](state); nextState.Normalize(_unit); Cell[] cells; if (!TryAddVisitedState(nextState, state, cmd[cmdIndex], out cells, out dummy, commandsStr[cmdIndex])) { // throw new Exception(); return startState; } state = nextState; } return state; }
public void Update(Unit unit, UnitState state) { Update(state.GetCells(unit)); }
public void TurnClockwise() { var unit = new Unit(new[] { new Cell(3, 0) }, new Cell(2, 3)); var unitState = new UnitState(unit.pivot, 0); unitState = UnitState.TurnClockwise(unitState); Assert.AreEqual(new Cell(2, 3), unitState.Pivot); Assert.AreEqual(new Cell(5, 2), unitState.GetCells(unit)[0]); unitState = UnitState.TurnClockwise(unitState); Assert.AreEqual(new Cell(4, 5), unitState.GetCells(unit)[0]); unitState = UnitState.TurnClockwise(unitState); Assert.AreEqual(new Cell(2, 6), unitState.GetCells(unit)[0]); unitState = UnitState.TurnClockwise(unitState); Assert.AreEqual(new Cell(0, 4), unitState.GetCells(unit)[0]); unitState = UnitState.TurnClockwise(unitState); Assert.AreEqual(new Cell(0, 1), unitState.GetCells(unit)[0]); unit = new Unit(new[] { new Cell(0, 2), new Cell(4, 2) }, new Cell(2, 2)); unitState = new UnitState(unit.pivot, 0); unitState = UnitState.TurnClockwise(unitState); var cells = unitState.GetCells(unit); Assert.AreEqual(2, cells.Length); Assert.IsTrue(cells.Contains(new Cell(1, 0))); Assert.IsTrue(cells.Contains(new Cell(3, 4))); unitState = UnitState.TurnClockwise(unitState); cells = unitState.GetCells(unit); Assert.IsTrue(cells.Contains(new Cell(3, 0))); Assert.IsTrue(cells.Contains(new Cell(1, 4))); }
private bool ApplySomePhrase(UnitState startState, PowerPhraseInfo prevPhrase, HashSet<UnitState> reachableStates, UnitState finalState, out UnitState stateAfterPhrase, out PowerPhraseInfo appliedPhrase, out List<int> reversedPathIfSuccess) { #if DEBUG DebugPrinter.WriteLine("Applying some phrase from state ({0}, {1}) rot {2}", startState.Pivot.x, startState.Pivot.y, startState.Rotation); #endif appliedPhrase = null; reversedPathIfSuccess = null; // apply current state of used phrases prevPhrase.PhraseCombinations.Sort(); int numFailed = 0; int combIdx = 0; foreach (var comb in prevPhrase.PhraseCombinations) { ++combIdx; if (combIdx > 7 && comb.NextPhrase.WasUsed && _field.Height * _field.Width > 400) break; //DebugPrinter.WriteLine(" Next combination: phrase \"{0}\", type {1}", comb.CommandsStr, comb.CombineType); foreach (List<int> moves in EnumeratePreparationMoves(comb.CombineType)) { var movesStr = MovesPrinter.PrintMoves(moves); //DebugPrinter.WriteLine(" Applying phrase \"{0}\" with additional moves {1}", comb.CommandsStr, movesStr); var cmdWithMovesStr = movesStr + comb.CommandsStr; var cmdWitmMoves = moves.Concat(comb.Commands).ToArray(); var oldVisited = new Dictionary<UnitState, VisitInfo>(_visited); stateAfterPhrase = ApplyPhrase(startState, cmdWithMovesStr, cmdWitmMoves); if ((stateAfterPhrase.Pivot != startState.Pivot || stateAfterPhrase.Rotation != startState.Rotation) && reachableStates.Contains(stateAfterPhrase) && _IsReachable(stateAfterPhrase, finalState, out reversedPathIfSuccess)) { appliedPhrase = comb.NextPhrase; appliedPhrase.WasUsed = true; #if DEBUG DebugPrinter.WriteLine("Apply succeeded with {0} failed attempts: phrase \"{1}\" with additional moves {2}", numFailed, comb.CommandsStr, movesStr); #endif return true; } _visited = oldVisited; ++numFailed; } } #if DEBUG DebugPrinter.WriteLine("Apply failed with {0} failed attempts", numFailed); #endif stateAfterPhrase = startState; return false; }
public static UnitState TurnCounter(UnitState state) { return new UnitState(state.Pivot, (state.Rotation + 1) % 6); }
private IEnumerable<List<int>> EnumeratePreparationMoves(CombineType combineType) { var moves = new List<int>(); if (combineType != CombineType.MoveDownAppend) { yield return moves; } if (combineType != CombineType.Overlap) { int maxDepth = 10; //_field.Width + 5; int[] firstMoves = combineType == CombineType.Append ? NON_DOWN_MOVES : DOWN_MOVES; var visited = new HashSet<UnitState>(); var stack = new List<MoveInfo>(); foreach (int firstMove in firstMoves) { var unitState = new UnitState(new Cell(0, 0), 0); UnitState newState = UnitState.MoveFuncs[firstMove](unitState); newState.Normalize(_unit); if (visited.Contains(newState)) continue; visited.Add(newState); stack.Add(new MoveInfo { Move = firstMove, NextMoveIdx = -1, UnitState = newState }); moves.Add(firstMove); while (stack.Count > 0) { var moveInfo = stack[stack.Count - 1]; if (moveInfo.NextMoveIdx == -1) yield return moves; ++moveInfo.NextMoveIdx; if (moveInfo.NextMoveIdx < NON_DOWN_MOVES.Length && stack.Count < maxDepth) { int move = NON_DOWN_MOVES[moveInfo.NextMoveIdx]; newState = UnitState.MoveFuncs[move](moveInfo.UnitState); newState.Normalize(_unit); if (visited.Contains(newState)) continue; visited.Add(newState); stack.Add(new MoveInfo { Move = move, NextMoveIdx = -1, UnitState = newState }); moves.Add(move); } else { stack.RemoveAt(stack.Count - 1); moves.RemoveAt(moves.Count - 1); } } } } }
public static UnitState MoveSW(UnitState state) { return new UnitState(Moves.MoveSW(state.Pivot), state.Rotation); }
public void TestUpdate() { var f = new Field(2, 2); var u = new Unit(new[] {new Cell(0, 0)}, new Cell(0, 0)); var us = new UnitState(new Cell(1, 1), 0); Assert.AreEqual(2, f.MinFilledRow); f.Update(u, us); Assert.AreEqual(true, f[1][1]); Assert.AreEqual(false, f[1][0]); Assert.AreEqual(1, f.MinFilledRow); Assert.IsTrue(f.RowCells(1).Contains(1)); Assert.IsFalse(f.RowCells(1).Contains(0)); Assert.AreEqual(f.RowCells(1).Count, 1); Assert.IsFalse(f.RowCells(0).Contains(0)); Assert.IsFalse(f.RowCells(0).Contains(1)); Assert.AreEqual(f.RowCells(0).Count, 0); Assert.AreEqual(1, f.Score); u = new Unit(new[] { new Cell(0, 0), new Cell(1, 0), new Cell(0, 1) }, new Cell(0, 0)); us = new UnitState(new Cell(0, 0), 0); f.Update(u, us); Assert.AreEqual(false, f[0][0]); Assert.AreEqual(false, f[0][1]); Assert.AreEqual(false, f[1][0]); Assert.AreEqual(false, f[1][1]); Assert.AreEqual(2, f.MinFilledRow); Assert.IsFalse(f.RowCells(1).Contains(1)); Assert.IsFalse(f.RowCells(1).Contains(0)); Assert.IsFalse(f.RowCells(0).Contains(0)); Assert.IsFalse(f.RowCells(0).Contains(1)); Assert.AreEqual(304, f.Score); u = new Unit(new[] { new Cell(0, 0), new Cell(1, 0), new Cell(0, 1), new Cell(1, 1) }, new Cell(0, 0)); us = new UnitState(new Cell(0, 0), 0); f.Update(u, us); Assert.AreEqual(false, f[0][0]); Assert.AreEqual(false, f[0][1]); Assert.AreEqual(false, f[1][0]); Assert.AreEqual(false, f[1][1]); Assert.AreEqual(2, f.MinFilledRow); Assert.IsFalse(f.RowCells(1).Contains(1)); Assert.IsFalse(f.RowCells(1).Contains(0)); Assert.IsFalse(f.RowCells(0).Contains(0)); Assert.IsFalse(f.RowCells(0).Contains(1)); Assert.AreEqual(638, f.Score); u = new Unit(new[] {new Cell(1, 0), new Cell(0, 1), new Cell(1, 1) }, new Cell(0, 0)); us = new UnitState(new Cell(0, 0), 0); f.Update(u, us); Assert.AreEqual(false, f[0][0]); Assert.AreEqual(false, f[0][1]); Assert.AreEqual(false, f[1][0]); Assert.AreEqual(true, f[1][1]); Assert.AreEqual(1, f.MinFilledRow); Assert.IsTrue(f.RowCells(1).Contains(1)); Assert.IsFalse(f.RowCells(1).Contains(0)); Assert.IsFalse(f.RowCells(0).Contains(0)); Assert.IsFalse(f.RowCells(0).Contains(1)); Assert.AreEqual(751, f.Score); u = new Unit(new[] { new Cell(0, 0), new Cell(1, 0) }, new Cell(0, 0)); us = new UnitState(new Cell(0, 0), 0); f.Update(u, us); Assert.AreEqual(false, f[0][0]); Assert.AreEqual(false, f[0][1]); Assert.AreEqual(false, f[1][0]); Assert.AreEqual(true, f[1][1]); Assert.AreEqual(1, f.MinFilledRow); Assert.IsTrue(f.RowCells(1).Contains(1)); Assert.IsFalse(f.RowCells(1).Contains(0)); Assert.IsFalse(f.RowCells(0).Contains(0)); Assert.IsFalse(f.RowCells(0).Contains(1)); Assert.AreEqual(853, f.Score); Assert.AreEqual(13, f.TotalBricks); Assert.AreEqual(2, f.RowsKilled[1]); Assert.AreEqual(2, f.RowsKilled[2]); }