コード例 #1
0
ファイル: MoveAction.cs プロジェクト: ProjectTane/FarenDotNet
 public override void Boot(ActionArguments args, WarUnit doer, Action finished)
 {
     var situation = args.Situation;
     var movableArea = situation.Map.MoveCalculator.CalcMovableArea(situation.Map, doer, doer.Location);
     _scope.CurrentMovableArea = movableArea;
     base.Boot(args, doer, finished);
 }
コード例 #2
0
        public virtual void Boot(ActionArguments args, WarUnit doer, Action finished)
        {
            var warAdapter = args.Model;

            IEnumerable<Point2> rangePoints;
            var validRangePoints = Scope.GetValidRangeScope(args.Situation, doer, out rangePoints).ToArray();
            if (validRangePoints.Length <= 0)
            {
                // HACK: メッセージボックス表示ルーチンの記述場所
                MessageBox.Show("射程内に有効な対象が存在しません.");
                args.Model.InvokeCancelEvent();
                return;
            }

            // スコープの位置に選択肢があれば、ユーザーに選択させる
            if (Scope.ExistChoice)
            {
                var pScope = new PrintableScope(Scope, rangePoints.ToArray(), validRangePoints, args.Situation, doer);

                // スコープを選択した際のイベント
                Action<Point2> selectMapChip = null;

                // スコープ選択状態を解除するデリゲート
                Action resetSelectScopeMode = () => {
                    warAdapter.Scope = null;
                    warAdapter.SelectMapChipEvent -= selectMapChip;
                };

                // スコープを選択した際のイベントの定義
                selectMapChip = p => {
                    if (warAdapter.Scope.ValidRangeChips.Contains(p))
                    {
                        // スコープ選択状態を解除
                        resetSelectScopeMode();
                        Execute(args, doer, p, finished);
                    }
                };

                // スコープの表示
                warAdapter.Scope = pScope;
                // スコープを選択した際のイベントを追加
                warAdapter.SelectMapChipEvent += selectMapChip;
                // キャンセルをした際のイベントを追加
                warAdapter.CancelCommandStack.Push(delegate {
                    resetSelectScopeMode();
                    return false; // 次のキャンセル処理へ続く
                });
            }
            else
            {
                Execute(args, doer, validRangePoints[0], finished);
            }
        }
コード例 #3
0
        protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine)
        {
            // 行為のキャンセルの不許可
            args.Model.CancelCommandStack.Clear();
            // コストの消費
            _cost.Expend(args.Situation, doer);

            // 攻撃アニメーションとその後の処理を予約する
            IEnumerable<Point2> areaPoints;
            var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints);
            _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, doCoroutine);
            yield return 0;		// エフェクト表示

            // 洪水処理
            var map = args.Situation.Map;
            var width = map.Width;
            var height = map.Height;
            var enableDamageAnimation = false;
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    var land = map[x, y];
                    if (land.Height <= TARGET_HEIGHT)
                    {
                        var taker = land.Unit;
                        if (taker != null && _attackType != AttackType.なし)
                        {
                            AdditionalEffect cond;
                            var damage = BattleActionUtil.GetMagicDamage(doer, taker, _power, _attackType, out cond);
                            BattleActionUtil.RunAttackRoutine(args, doer, taker, damage, cond, doCoroutine);
                            enableDamageAnimation = true;
                        }

                        // マップの更新
                        if (brinkNames.Contains(land.Info.Name))
                        {
                            map[x, y] = new Land(land.Height - TARGET_HEIGHT, land.Landform, null);
                        }
                        else
                        {
                            map[x, y] = new Land(land.Height - TARGET_HEIGHT, _brinkLandform, null);
                        }
                    }
                }
            }
            if (enableDamageAnimation)
                yield return 0;		// ダメージ表示

            finished();
        }
コード例 #4
0
        protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine)
        {
            // 行為のキャンセルの不許可
            args.Model.CancelCommandStack.Clear();
            // コストの消費
            _cost.Expend(args.Situation, doer);

            // 攻撃アニメーションとその後の処理を予約する
            IEnumerable<Point2> areaPoints;
            var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints);
            _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, doCoroutine);
            yield return 0;		// エフェクト表示

            foreach (var p in validPoints)
            {
                var taker = args.Situation.Map[p].Unit;
                taker.Conditions.Add(_cond, args.Situation);
            }
            finished();
        }
コード例 #5
0
        protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine)
        {
            // 行為のキャンセルの不許可
            args.Model.CancelCommandStack.Clear();

            Debug.Assert(args.Situation.Map[center].Unit != null, "選択位置にユニットが存在しません.");
            var taker = args.Situation.Map[center].Unit;

            var doerAttack = doer.Status.DefaultAttacks.Select(atk => new { Doer = doer, Taker = taker, atk.Type, atk.Power });
            var takerAttack = taker.Status.DefaultAttacks.Select(atk => new { Doer = taker, Taker = doer, atk.Type, atk.Power });
            var source = doerAttack.AlternatelyConcat(takerAttack)
                .Where(info => info.Type != AttackType.なし);

            foreach (var info in source)
            {
                // ローカル変数にも代入しておく(ごっちゃにならないように)
                doer = info.Doer;
                taker = info.Taker;
                // アニメーション中は、マップ上のユニット表示をオフにする
                doer.Visible = false;
                // 攻撃アニメーションとその後の処理を予約する
                args.Model.SetContinuouslyMovingAnimationOnMap(
                    doer.ChipImage, new[] { doer.Location, taker.Location, doer.Location },
                    args.Model.ATTACK_EFFECT_TIME, 0, doCoroutine);
                yield return 0;		// エフェクト表示

                doer.Visible = true;

                AdditionalEffect cond;
                var damage = BattleActionUtil.GetDamage(doer, taker, info.Power, info.Type, out cond);
                BattleActionUtil.RunAttackRoutine(args, doer, taker, damage, cond, doCoroutine);
                yield return 0;		// ダメージ表示

                // どちらかが死亡したら処理を中断
                if (!doer.Alive || !taker.Alive)
                    break;
            }

            finished();
        }
コード例 #6
0
        protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine)
        {
            // 行為のキャンセルの不許可
            args.Model.CancelCommandStack.Clear();
            // コストの消費
            _cost.Expend(args.Situation, doer);

            IEnumerable<Point2> areaPoints;
            var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints);
            var times = XMath.Center(doer.SkillTimes, 1, _maxTimes);

            _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, times, (times_, maxTimes_) => {
                foreach (var p in validPoints)
                {
                    var taker = args.Situation.Map[p].Unit;
                    AdditionalEffect cond;
                    var value = BattleActionUtil.GetSkillValue(doer, taker, _power, _attackType,
                        _atkDependency, _defDependency, out cond);
                    var action = times_ < maxTimes_ ? doCoroutine.GetNOP() : doCoroutine;

                    if (_attackType != AttackType.体力回復 && _attackType != AttackType.魔力回復)
                    {
                        BattleActionUtil.RunAttackRoutine(args, doer, taker, value, cond, action);
                    }
                    else
                    {
                        if (_attackType == AttackType.体力回復)
                            taker.HealHP(args.Situation, doer, value);
                        else
                            taker.HealMP(args.Situation, doer, value);
                        // 回復値の表示
                        args.Model.SetHealAnimationOnMap(value, doer.Location, action);
                    }
                }
            });
            yield return 0; // 最後のダメージ表示

            finished();
        }
コード例 #7
0
        protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine)
        {
            // 行為のキャンセルの不許可
            args.Model.CancelCommandStack.Clear();
            // コストの消費
            _cost.Expend(args.Situation, doer);

            // 攻撃アニメーションとその後の処理を予約する
            IEnumerable<Point2> areaPoints;
            var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints);
            _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, doCoroutine);
            yield return 0; // エフェクト表示

            foreach (var p in validPoints)
            {
                Debug.Assert(args.Situation.Map[p].Unit == null);
                var unit = WarGlobal.UnitBuilder.Create(new Unit(_unit), doer.Side, null);
                args.Situation.Units.AddUnit(unit);
                args.Situation.Map.Deploy(unit, p);
            }

            finished();
        }
コード例 #8
0
        protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine)
        {
            // 行為のキャンセルの不許可
            args.Model.CancelCommandStack.Clear();
            // コストの消費
            _cost.Expend(args.Situation, doer);

            // 攻撃アニメーションとその後の処理を予約する
            IEnumerable<Point2> areaPoints;
            var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints);
            _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, doCoroutine);
            yield return 0; // エフェクト表示

            // 対象内の壁を破壊
            var map = args.Situation.Map;
            var enableDamageAnimation = false;
            foreach (var p in areaPoints)
            {
                var land = map[p];
                if (land.Construct != null && land.Construct.Info.Name == "壁")
                {
                    map[p] = new Land(land.Height, land.Landform, null);
                    if (land.Unit != null && _attackType != AttackType.なし)
                    {
                        var taker = land.Unit;
                        AdditionalEffect cond;
                        var damage = BattleActionUtil.GetMagicDamage(doer, taker, _power, _attackType, out cond);
                        BattleActionUtil.RunAttackRoutine(args, doer, taker, damage, cond, doCoroutine);
                        enableDamageAnimation = true;
                    }
                }
            }
            if (enableDamageAnimation)
                yield return 0;		// ダメージ表示

            finished();
        }
コード例 #9
0
        protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine)
        {
            // 行為のキャンセルの不許可
            args.Model.CancelCommandStack.Clear();
            // コストの消費
            _cost.Expend(args.Situation, doer);

            // 攻撃アニメーションとその後の処理を予約する
            IEnumerable<Point2> areaPoints;
            var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints);
            _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, doCoroutine);
            yield return 0;		// エフェクト表示

            foreach (var p in validPoints)
            {
                var taker = args.Situation.Map[p].Unit;
                if (!AttackTypes.Heal.Contains(_attackType))
                {
                    AdditionalEffect cond;
                    var damage = BattleActionUtil.GetMagicDamage(doer, taker, _power, _attackType, out cond);
                    BattleActionUtil.RunAttackRoutine(args, doer, taker, damage, cond, doCoroutine);
                }
                else
                {
                    var value = BattleActionUtil.GetMagicHeal(doer, taker, _power);
                    if (_attackType == AttackType.体力回復)
                        taker.HealHP(args.Situation, doer, value);
                    else
                        taker.HealMP(args.Situation, doer, value);
                    // 回復値の表示
                    args.Model.SetHealAnimationOnMap(value, doer.Location, doCoroutine);
                }
            }
            yield return 0;		// ダメージ表示

            finished();
        }
コード例 #10
0
ファイル: MoveAction.cs プロジェクト: ProjectTane/FarenDotNet
        protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine)
        {
            // キャンセル処理のために記憶する
            var oldLocation = doer.Location;
            var resetCommandState = doer.SaveCommandState();

            // 移動アニメーション用に経路を生成する
            var movePoints = new Stack<Point2>();
            var movePoint = _scope.CurrentMovableArea.Find(p => p.Point == center);
            while (movePoint != null)
            {
                movePoints.Push(movePoint.Point);
                movePoint = movePoint.From;
            }

            // アニメーション中は、マップ上のユニット表示をオフにする
            doer.Visible = false;
            // 移動アニメーションのセット
            args.Model.SetContinuouslyMovingAnimationOnMap(doer.ChipImage, movePoints, 150, 20, doCoroutine);
            yield return 0;		// 移動アニメーションの表示

            // アニメーション後に元に戻す
            doer.Visible = true;
            args.Situation.Map.MoveUnit(doer, center);

            // アクション終了の通知
            finished();

            // 移動前に戻すキャンセル処理の追加
            args.Model.CancelCommandStack.Push(
                () => {
                    args.Situation.Map.MoveUnit(doer, oldLocation);
                    resetCommandState();
                    return false;	// キャンセル処理の続行
                });
        }
コード例 #11
0
        public virtual void BootAI(ActionArguments args, WarUnit doer, Action finished)
        {
            //わざと何も処理してません

            //何か処理したければオーバーライドしてください
        }
コード例 #12
0
 /// <summary>
 ///  行為が発動可能かどうかチェックする
 /// </summary>
 /// <param name="args">アクションの引数</param>
 /// <param name="doer">行為者</param>
 /// <returns>
 /// 発動可能かどうか
 /// </returns>
 public override bool CanBoot(ActionArguments args, WarUnit doer)
 {
     return _cost.CanExpend(doer) &&
         args.Situation.Units.Alive.Any(unit_ => unit_.IsUndead);
 }
コード例 #13
0
 protected abstract IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine);
コード例 #14
0
 public override void Execute(ActionArguments args, WarUnit doer, Point2 center, Action finished)
 {
     IEnumerator<int> enumerator = null;
     enumerator = GetCoroutine(args, doer, center, finished,
         () => enumerator.MoveNext()).GetEnumerator();
     enumerator.MoveNext();
 }
コード例 #15
0
        public static void RunAttackRoutine(ActionArguments args, WarUnit doer, WarUnit taker,
            int value, AdditionalEffect effect, Action finishAnimation)
        {
            switch (effect)
            {
            case AdditionalEffect.なし:
                break;
            case AdditionalEffect.毒:
                taker.Conditions.Add(new PoisonCondition(), args.Situation);
                break;
            case AdditionalEffect.石化:
                taker.Conditions.Add(new PetrifactionCondition(), args.Situation);
                break;
            case AdditionalEffect.麻痺:
                taker.Conditions.Add(new ParalysisCondition(), args.Situation);
                break;
            case AdditionalEffect.眠り:
                taker.Conditions.Add(new SleepCondition(), args.Situation);
                break;
            case AdditionalEffect.幻想:
                // TODO: 実装
                break;
            case AdditionalEffect.死:
                taker.Die(args.Situation, doer);
                break;
            case AdditionalEffect.吸収:
                // 回復値の表示
                doer.HealHP(args.Situation, doer, value);
                args.Model.SetHealAnimationOnMap(value, doer.Location, null);
                break;
            default:
                throw new ArgumentOutOfRangeException("effect");
            }

            // ダメージの表示要請
            taker.DamageHP(args.Situation, doer, value);
            args.Model.SetDamageAnimationOnMap(value, taker.Location, finishAnimation);
        }
コード例 #16
0
 public void Execute(ActionArguments args, WarUnit doer, Action finished)
 {
     args.Situation.PhaseManager.ExitPhase(args.Situation);
     finished();
 }
コード例 #17
0
 public override bool CanBoot(ActionArguments args, WarUnit doer)
 {
     return _cost.CanExpend(doer);
 }
コード例 #18
0
 public abstract bool CanBoot(ActionArguments args, WarUnit doer);
コード例 #19
0
 public bool CanExecute(ActionArguments args, WarUnit doer)
 {
     return _action.CanBoot(args, doer);
 }
コード例 #20
0
 public override bool CanBoot(ActionArguments args, WarUnit doer)
 {
     return _cost.CanExpend(doer) &&
         args.Situation.Map.Any(land_ => brinkNames.Contains(land_.Info.Name));
 }
コード例 #21
0
 public void Execute(ActionArguments args, WarUnit doer, Action finished)
 {
     _action.Boot(args, doer, finished);
 }
コード例 #22
0
 public abstract void Execute(ActionArguments args, WarUnit doer, Point2 center, Action finished);
コード例 #23
0
        private Button GetButton(IBattleCommand cmd)
        {
            Button btn;
            if (!buttons.TryGetValue(cmd, out btn))
            {
                // クリックしたときに実行されるコマンド
                // 作成されるボタン
                btn = new Button {
                    Margin = new Padding(0),
                    Size = new Size(48, 48),
                    Image = cmd.Image,
                    Text = cmd.Image == null ? cmd.Name : "",
                };
                buttons[cmd] = btn;
                // マウスオーバーで表示される文字
                toolTip.SetToolTip(btn, cmd.Description);
                // クリック時のイベントを設定
                btn.Click += delegate {
                    flowLayoutPanel.Enabled = false;
                    var doer = Situation.ActiveUnit;

                    // キャンセル時の処理はGUIの実装に依存するためここに記述
                    Action finished = () => {
                        doer.ChangeCommandState(cmd);
                        ResetCommandButtons();
                        flowLayoutPanel.Enabled = true;
                    };
                    model.CancelCommandStack.Push(() => {
                        ResetCommandButtons();
                        flowLayoutPanel.Enabled = true;
                        return true; // キャンセル処理の完了
                    });
                    var arc = new ActionArguments(Situation, model);
                    cmd.Execute(arc, doer, finished);
                };
            }
            return btn;
        }
コード例 #24
0
        protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine)
        {
            // 行為のキャンセルの不許可
            args.Model.CancelCommandStack.Clear();
            // コストの消費
            _cost.Expend(args.Situation, doer);

            // 攻撃アニメーションとその後の処理を予約する
            IEnumerable<Point2> areaPoints;
            var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints);
            _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, doCoroutine);
            yield return 0;		// エフェクト表示

            var lf = WarGlobal.Landforms;
            var landforms = new[,] {
                { lf[152], lf[143], lf[143], lf[143], lf[143], lf[153], null, null, null, null, null, },
                { lf[159], lf[172], lf[163], lf[163], lf[163], lf[172], lf[158], null, null, null, null, },
                { lf[159], lf[179], lf[172], lf[163], lf[163], lf[173], lf[178], lf[158], null, null, null, },
                { lf[159], lf[179], lf[179], lf[172], lf[163], lf[173], lf[178], lf[178], lf[158], null, null, },
                { lf[159], lf[179], lf[179], lf[179], lf[141], lf[141], lf[178], lf[178], lf[178], lf[158], null, },
                { lf[144], lf[164], lf[164], lf[164], lf[141], lf[141], lf[141], lf[165], lf[165], lf[165], lf[145], },
                { null, lf[156], lf[176], lf[176], lf[176], lf[141], lf[141], lf[177], lf[177], lf[177], lf[157], },
                { null, null, lf[156], lf[176], lf[176], lf[174], lf[162], lf[175], lf[177], lf[177], lf[157], },
                { null, null, null, lf[156], lf[176], lf[174], lf[162], lf[162], lf[175], lf[177], lf[157], },
                { null, null, null, null, lf[156], lf[174], lf[162], lf[162], lf[162], lf[175], lf[157], },
                { null, null, null, null, null, lf[154], lf[142], lf[142], lf[142], lf[142], lf[155], },
            };
            var heights = new[,] {
                { 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, },
                { 4, 5, 5, 5, 5, 5, 4, 0, 0, 0, 0, },
                { 4, 5, 6, 6, 6, 6, 5, 4, 0, 0, 0, },
                { 4, 5, 6, 7, 7, 7, 6, 5, 4, 0, 0, },
                { 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 0, },
                { 4, 5, 6, 7, 8, 8, 8, 7, 6, 5, 4, },
                { 0, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, },
                { 0, 0, 4, 5, 6, 7, 7, 7, 6, 5, 4, },
                { 0, 0, 0, 4, 5, 6, 6, 6, 6, 5, 4, },
                { 0, 0, 0, 0, 4, 5, 5, 5, 5, 5, 4, },
                { 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, },
            };

            // 地形書き換え処理
            var map = args.Situation.Map;
            var sx = center.X - 5;
            var sy = center.Y - 5;

            foreach (var p in validPoints)
            {
                var taker = args.Situation.Map[p].Unit;
                AdditionalEffect cond;
                var damage = BattleActionUtil.GetMagicDamage(doer, taker, _power, _attackType, out cond);
                BattleActionUtil.RunAttackRoutine(args, doer, taker, damage, cond, doCoroutine);
            }

            foreach (var p in areaPoints)
            {
                // マップの更新
                map[p] = new Land(heights[p.Y - sy, p.X - sx], landforms[p.Y - sy, p.X - sx], null);
            }
            yield return 0;		// ダメージ表示

            finished();
        }
コード例 #25
0
 public bool CanExecute(ActionArguments args, WarUnit doer)
 {
     return false;
 }
コード例 #26
0
ファイル: MoveAction.cs プロジェクト: ProjectTane/FarenDotNet
 public override bool CanBoot(ActionArguments args, WarUnit doer)
 {
     return true;
 }
コード例 #27
0
 public void Execute(ActionArguments args, WarUnit doer, Action finished)
 {
     finished();
 }
コード例 #28
0
        /// <summary>
        /// このウインドウを表示する
        /// </summary>
        /// <param name="model"></param>
        /// <param name="doer"></param>
        /// <param name="finished"></param>
        /// <param name="index">魔法の属性を示すインデックス値</param>
        public void Show(WarPresentationModel model, WarUnit doer, Action finished, int index)
        {
            Debug.Assert(0 <= index && index <= 5, "予期せぬindex値を受け取りました: " + index);

            _model = model;
            var situation = model.Situation;

            // ボタンの全消去
            flowButtonPanel.Controls.Clear();

            // ボタンの追加
            var magicDatasList = _magicCommands[index, doer.MagicLevels[magicAttributes[index]]];
            for (int j = 0; j < magicDatasList.Count; j++)
            {
                var magicDatas = magicDatasList[j];
                for (int i = 0; i < magicDatas.Count; i++)
                {
                    var magicData = magicDatas[i];
                    var arc = new ActionArguments(situation, model);

                    var button = new Button {
                        Enabled = magicData.Action.CanBoot(arc, doer),
                        Text = magicData.Name + (i + 1),
                    };
                    button.Click += (sender_, e_) => {
                        Visible = false;
                        model.CancelCommandStack.Push(delegate {
                            Visible = true;
                            return true; // キャンセル処理の完了
                        });
                        magicData.Action.Boot(arc, doer, finished);
                    };
                    button.MouseEnter += delegate { PointingMagic = magicData; };
                    button.MouseLeave += delegate { PointingMagic = null; };
                    flowButtonPanel.Controls.Add(button);
                }
            }

            SetDetail(null);
            Text = doer.Name;
            Visible = true;
        }
コード例 #29
0
        protected virtual void CreateInitiativePhase(WarPresentationModel model, List<List<WarUnit>> friendUnits, List<WarUnit> enemyUnits, MainWindow mainWindow)
        {
            Phases.InitiativePhase.Start = situation_ =>
            {
                model.MapWindow.Refresh();
                if (situation_.ActiveUnit.Side.IsPlayer)
                {
                    // ユニットのコマンド状態を初期化する
                    situation_.ActiveUnit.ResetCommandState();
                }
                else
                {
                    #region AI

                    var doer = situation_.ActiveUnit;
                    var ar = new ActionArguments(situation_, model);

                    var actionEnumrator = new AI.AI().GetActionWithCoroutine(situation_);

                    Action actionCoroutine = null;

                    // AIの行動選択と実行のコルーチン
                    actionCoroutine = () =>
                    {
                        // 非同期実行のためのAIの行動選択デリゲートの生成
                        Func<bool> selectNextAction = actionEnumrator.MoveNext;
                        var asyncResult = selectNextAction.BeginInvoke(null, null);

                        // TaskList にAIの行動選択完了後の、戦闘行動実行を予約する
                        // TaskList を使うことで、ウィンドウメッセージ処理のスレッドによる同期実行が行われる
                        TaskList<int>.Task task = null;
                        task = (taskArgs_, time_) =>
                        {
                            // 非同期実行が完了するまでは何もしない
                            if (!asyncResult.IsCompleted) return;

                            // 非同期実行が完了すれば、戻り値を取得する
                            if (selectNextAction.EndInvoke(asyncResult))
                            {
                                // AIが選択したActionが存在する
                                var battleAction = actionEnumrator.Current.Item1;
                                battleAction.BootAI(ar, doer, Delegates.NOP);
                                battleAction.Execute(ar, doer, actionEnumrator.Current.Item2, actionCoroutine);
                            }
                            else
                            {
                                // AIが選択したActionが存在しないので、ユニットの行動終了
                                situation_.PhaseManager.ExitPhase(situation_);
                            }
                            // タスクリストからこのデリゲートを削除する
                            Global.MainLoop.TickEvents.Remove(task);
                        };
                        Global.MainLoop.TickEvents.Add(Double.MinValue, task);
                    };

                    // AIの行動選択と実行のコルーチンを実行
                    actionCoroutine();

                    #endregion
                }
            };

            Phases.InitiativePhase.Exit = situation_ =>
            {
                var friends = situation_.Sides.Single(side => side.IsPlayer);
                var enemies = situation_.Sides.Single(side => !side.IsPlayer);

                _result = checkBattleEnd(situation_, friends, enemies);
                if (_result != BattleResult.None)
                {
                    situation_.PhaseManager.ExitPhase(situation_);
                    return;
                }

                model.CancelCommandStack.Clear();
                situation_.ActiveUnit.Side.UpdateForceAndBrave(situation_.Units.Alive);

                var unit = situation_.TurnManager.GetInitiativeUnit(situation_);
                if (unit != null)
                {
                    situation_.ActiveUnit = unit;
                    situation_.PhaseManager.StartPhase(situation_, Phases.InitiativePhase);
                }
                else
                {
                    situation_.PhaseManager.ExitPhase(situation_);
                }
            };
        }