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 PowerPhraseData(PowerPhraseInfo[] phrases, PhraseMetricType metricType) { Phrases = phrases; //_combineInfo = new CombineInfo[phrases.Length, phrases.Length]; foreach (var p in Phrases) p.EffectiveLength = CalcEffectiveLen(p.Phrase); foreach (var p1 in phrases) { p1.InitCombinations(this, metricType); } }
public void Test1() { var phrase1 = new PowerPhraseInfo("ei!", 0); Assert.AreEqual(1, phrase1.DY); Assert.AreEqual(-1, phrase1.MinX); Assert.AreEqual(1, phrase1.MaxX); Assert.IsFalse(phrase1.CanRepeatImmediately); var phrase2 = new PowerPhraseInfo("ia! ia!", 0); Assert.AreEqual(5, phrase2.DY); Assert.AreEqual(-4, phrase2.MinX); Assert.AreEqual(0, phrase2.MaxX); Assert.IsTrue(phrase2.CanRepeatImmediately); }
int ComparePhrases(PowerPhraseInfo p1, PowerPhraseInfo p2) { if (!p1.WasUsed && p2.WasUsed) return -1; if (p1.WasUsed && !p2.WasUsed) return 1; return p2.Metric.CompareTo(p1.Metric); }
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; }
private bool ApplySomePhrase(BfsState startBfsState, PowerPhraseInfo prevPhrase, out BfsState stateAfterPhrase, out PowerPhraseInfo appliedPhrase) { DebugPrinter.WriteLine("Applying some phrase from state ({0}, {1}) rot {2}", startBfsState.UnitState.Pivot.x, startBfsState.UnitState.Pivot.y, startBfsState.UnitState.Rotation); stateAfterPhrase = startBfsState; appliedPhrase = null; // apply current state of used phrases prevPhrase.PhraseCombinations.Sort(); int numFailed = 0; foreach (var comb in prevPhrase.PhraseCombinations) { 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(); stateAfterPhrase = ApplyPhrase(startBfsState, cmdWithMovesStr, cmdWitmMoves); if (stateAfterPhrase.UnitState.Pivot != startBfsState.UnitState.Pivot || stateAfterPhrase.UnitState.Rotation != startBfsState.UnitState.Rotation) { appliedPhrase = comb.NextPhrase; appliedPhrase.WasUsed = true; DebugPrinter.WriteLine("Apply succeeded with {0} failed attempts", numFailed); return true; } ++numFailed; } } DebugPrinter.WriteLine("Apply failed with {0} failed attempts", numFailed); return false; }
private BfsState ApplyPhraseManyTimes(BfsState startState, PowerPhraseInfo phraseInfo) { BfsState lastValidState = startState; for (;;) { var newBfsState = ApplyPhrase(lastValidState, phraseInfo); if (newBfsState == lastValidState) return lastValidState; lastValidState = newBfsState; if (phraseInfo.CanRepeatImmediately) continue; if (!lastValidState.IsAbove(_field.MinFilledRow - 1)) return lastValidState; // try to move SW or SE to repeat the phrase after that for (MoveType funcIndex = MoveType.SW; funcIndex <= MoveType.SE; ++funcIndex) { UnitState newUnitState = UnitState.MoveFuncs[(int)funcIndex](lastValidState.UnitState); Cell[] cells; bool dummy; if (TryAddVisitedState(newUnitState, lastValidState.UnitState, (int)funcIndex, out cells, out dummy)) { lastValidState = new BfsState(newUnitState, cells); break; } } } }
private BfsState ApplyPhrase(BfsState startState, PowerPhraseInfo phraseInfo) { if (phraseInfo == null || string.IsNullOrEmpty(phraseInfo.Phrase)) return startState; return ApplyPhrase(startState, phraseInfo.Phrase, phraseInfo.Commands); }