예제 #1
0
        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);
        }
예제 #2
0
파일: BFS.cs 프로젝트: martugin/tetris
        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;
                }
            }
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
파일: Algo1.cs 프로젝트: martugin/tetris
        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);
        }
예제 #6
0
파일: BFS2.cs 프로젝트: martugin/tetris
        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;
        }
예제 #7
0
파일: BFS.cs 프로젝트: martugin/tetris
        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;
        }
예제 #8
0
파일: BFS.cs 프로젝트: martugin/tetris
        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;
                    }
                }
            }
        }
예제 #9
0
파일: BFS.cs 프로젝트: martugin/tetris
        private BfsState ApplyPhrase(BfsState startState, PowerPhraseInfo phraseInfo)
        {
            if (phraseInfo == null || string.IsNullOrEmpty(phraseInfo.Phrase))
                return startState;

            return ApplyPhrase(startState, phraseInfo.Phrase, phraseInfo.Commands);
        }