Ejemplo n.º 1
0
        /// <summary>
        /// 削除できる可能性のあるスライムの分析する
        /// </summary>
        /// <param name="context">フィールド状態</param>
        /// <param name="player">プレイヤ</param>
        /// <param name="param">パラメータ</param>
        /// <returns>削除できる可能性のあるスライム数</returns>
        public int Analyze(FieldContext context, Player.Index player, Param param)
        {
            Debug.Assert(param.TargetSlime != Slime.None, "対象スライムがNoneはありえません");

            var _context = context.DeepCopy();

            // フィールドから削除対象のスライムを削除する
            foreach (var slime in param.ErasedSlimes)
            {
                if (slime == param.TargetSlime)
                {
                    continue;
                }
                _context.SlimeFields[(int)player][slime] = Enumerable.Range(0, FieldContextConfig.FieldUnitCount).Select(i => 0u).ToArray();
            }

            // 移動可能スライムも落下させたいので、情報のみ場外においやってしまう
            MovableSlime.ForEach(index =>
            {
                var movable      = _context.MovableSlimes[(int)player][(int)index];
                movable.Index    = 0;
                movable.Position = (int)index;
            });

            // 重力ですべて落下させる
            this.Gravity.Update(_context, player, GravityParam);

            // スライムを消済にマーキングする
            this.ErasingMarker.Update(_context, player, ErasingMarkerParam);

            // 消済スライム数をカウントする
            return(SlimeCountHelper.GetSlimeCount(_context, player, Slime.Erased));
        }
Ejemplo n.º 2
0
        public int Analyze(FieldContext context, Player.Index player)
        {
            var min = 99;
            var max = -99;

            for (var column = FieldContextConfig.OneLineBitCount - FieldContextConfig.VerticalLineLength; column < FieldContextConfig.OneLineBitCount; column++)
            {
                var exists = false;
                for (var unit = FieldContextConfig.MaxHiddenUnitIndex + 1; unit < FieldContextConfig.FieldUnitCount; unit++)
                {
                    for (var line = 0; line < FieldContextConfig.FieldUnitLineCount; line++)
                    {
                        exists = FieldContextHelper.ExistsSlime(context, player, unit, column + (line * FieldContextConfig.OneLineBitCount));
                        if (exists)
                        {
                            var top = (unit - FieldContextConfig.MaxHiddenUnitIndex + 1) * FieldContextConfig.FieldUnitLineCount + line;
                            min = Math.Min(top, min);
                            max = Math.Max(top, max);
                            break;
                        }
                    }
                    if (exists)
                    {
                        break;
                    }
                }
            }

            min = min == 99 ? 0 : min;
            max = max == -99 ? 0 : max;
            return(max - min);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// 起こりうる最大連鎖回数を分析します
        /// </summary>
        /// <returns>起こりうる最大連鎖回数</returns>
        /// <param name="context">フィールド状態</param>
        /// <param name="player">プレイヤ</param>
        public int Analyze(FieldContext context, Player.Index player)
        {
            int maxChain = 0;

            // 移動可能パターンを取得
            var movePatterns = CompleteReadingHelper.GetAllMovePatterns();

            // 分析対象の移動可能スライムを生成
            var usingSlimes   = context.UsingSlimes;
            var slimePatterns = new List <Slime[]>();

            slimePatterns.Add(new[] { usingSlimes[0], usingSlimes[1] });
            slimePatterns.Add(new[] { usingSlimes[2], usingSlimes[3] });

            // 自動移動機能を生成
            var updater = DiProvider.GetContainer().GetInstance <AutoMoveAndDropUpdater>();

            updater.Inject(context.UsingSlimes);

            // 各移動可能スライムの全パターンを試していく
            foreach (var slimePattern in slimePatterns)
            {
                var _context = context.DeepCopy();
                // 移動可能スライムを書き換える
                for (var movable = 0; movable < MovableSlime.Length; movable++)
                {
                    var org   = _context.MovableSlimes[player.ToInt()][(int)movable];
                    var valid = (org.Index == FieldContextConfig.MaxHiddenUnitIndex &&
                                 org.Position == FieldContextConfig.MovableSlimeInitialShiftAfterDroped + (FieldContextConfig.OneLineBitCount * (int)movable));
                    if (!valid)
                    {
                        return(0);
                    }

                    // 元の移動可能スライムを消す
                    _context.SlimeFields[player.ToInt()][org.Slime][org.Index] &= ~(1u << org.Position);

                    // 色を書き換える
                    org.Slime = slimePattern[(int)movable];
                }

                // 自動移動を実行
                foreach (var movePattern in movePatterns)
                {
                    var _movedContext = _context.DeepCopy();
                    var param         = new AutoMoveAndDropUpdater.Param()
                    {
                        Pattern = movePattern,
                    };

                    updater.Update(_movedContext, player, param);
                    maxChain = Math.Max(maxChain, param.Chain);
                }
            }

            // 試行内の最大連鎖数を返却
            return(maxChain);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// 2プレイヤ分のフィールド情報 + NEXTスライム情報の文字列から対象プレイヤのフィールド文字列のみを抽出します。
        /// </summary>
        /// <param name="orgLines">2プレイヤ分のフィールド情報 + NEXTスライム情報の文字列</param>
        /// <param name="player">対象プレイヤ</param>
        /// <returns>対象プレイヤのフィールド文字列</returns>
        private static List <string> ExtractOnePlayerFieldLines(string[] orgLines, Player.Index player)
        {
            var targetIndex = player == Player.Index.First ? FieldIndex.FirstPlayer : FieldIndex.SecondPlayer;
            var lines       = new List <string>();

            foreach (var orgLine in orgLines)
            {
                // 対象プレイヤのフィールド情報を取得
                var line = orgLine.Split(SimpleText.Separator.Player);
                lines.Add(line[(int)targetIndex]);
            }

            Debug.Assert(lines.Count() == SimpleText.Length.Field - 1, "フィールドの行数が不正です。行数:" + lines.Count());
            return(lines);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// 自動移動を実行します。
        /// </summary>
        /// <param name="context">フィールド状態</param>
        /// <param name="player">プレイヤ</param>
        /// <param name="param">パラメータ</param>
        public void Update(FieldContext context, Player.Index player, Param param)
        {
            Debug.Assert(this.HasInjected, "依存性の注入が完了していません");
            if (!(context.FieldEvent[(int)context.OperationPlayer] == FieldEvent.None || context.FieldEvent[(int)context.OperationPlayer] == FieldEvent.End))
            {
                return;
            }
#if DEBUG
            for (var i = 0; i < context.UsingSlimes.Length; i++)
            {
                Debug.Assert(context.UsingSlimes[i] == this.UsingSlimes[i], "使用スライムが不正です");
            }
#endif

            // 回転と横移動
            foreach (var p in param.Pattern)
            {
                context.OperationDirection = p;
                context = this.Game.Update(context);
            }

            // 最後まで落下させる
            while (!context.Ground[(int)player] && context.FieldEvent[(int)player] != FieldEvent.End)
            {
                context.OperationDirection = Direction.Down;
                context = this.Game.Update(context);
            }

            // 接地したら即設置完了にする
            context.BuiltRemainingTime[(int)player] = -1;
            context.OperationDirection = Direction.None;
            context = this.Game.Update(context);

            // イベント終了 or ゲーム終了まで更新する
            while (context.FieldEvent[(int)player] != FieldEvent.None && context.FieldEvent[(int)player] != FieldEvent.End)
            {
                context     = this.Game.Update(context);
                param.Chain = Math.Max(param.Chain, context.Chain[player.ToInt()]);
            }
            Debug.Assert(context.FieldEvent[(int)player] == FieldEvent.None || context.FieldEvent[(int)player] == FieldEvent.End, "イベント発生中はありえません");
        }